def el_multirun(elm):
    
    #separating each line from atom data
    atomtrim = pf.FileAtoms()
    atomtrim.load(atomdata)
    atomtrim.cut(mainfile.llzero, mainfile.llfin)
    atomel = pf.FileAtoms()
    atomel.atoms = [a for a in atomtrim.atoms if a.elem == pf.adjust_atomic_symbol(elm)]
    
    speclines = []
    line_num_specs = []
    
    #configuring multi-running for each line
    el_combos = []
    for atom in atomel.atoms:
        for line in atom.lines:
            
            singline = pf.FileAtoms()
            a = copy.copy(atom)
            a.lines = [line]
            singline.atoms = [a]
    
            cm = pf.Combo([pf.FOR_PFANT, pf.FOR_NULBAD])
            cm.conf.flag_output_to_dir = True
            cm.conf.flag_log_console = False
            cm.conf.opt.no_molecules = True
            cm.conf.opt.absoru = True
            cm.conf.opt.opa = False
            cm.conf.file_main = mainfile
            cm.conf.file_abonds = abondsfile
            cm.conf.file_atoms = singline
            cm.conf.file_main = mainfile
            cm.conf.opt.fn_cv = cm.conf.file_main.flprefix + ".norm.nulbad.%5.3f" % mainfile.fwhm
            
            el_combos.append(cm)
    
    #run pfant-multi
    pf.run_parallel(el_combos, flag_console=False)
    
    #load results and save spectra into lists
    i = 0
    for atom in atomel.atoms:
        for line in atom.lines:
            pl = el_combos[i].pfant
            n = el_combos[i].nulbad
    
            n.load_result()
            n.convolved.filename = str(line.lambda_)
            
            speclines.append(n.convolved)
            
            lbdfluxpec = [n.convolved.x, n.convolved.y]
            line_num_specs.append(lbdfluxpec)
            
            pl.conf.sid.clean()
            
            i += 1
    
    return speclines, line_num_specs
Example #2
0
"""Runs synthesis for specified atomic species separately. No molecules or hydrogen lines."""

import pyfant
import f311
import matplotlib.pyplot as plt
import a99

# ["<element name><ionization level>", ...] for which to draw panels
MY_SPECIES = ["Fe1", "Fe2", "Ca1", "Ca2", "Na1", "Si1"]

if __name__ == "__main__":
    pyfant.copy_star(starname="sun-grevesse-1996")
    pyfant.link_to_data()

    # Loads full atomic lines file
    fatoms = pyfant.FileAtoms()
    fatoms.load()

    runnables = []
    for elem_ioni in MY_SPECIES:
        atom = fatoms.find_atom(elem_ioni)

        # Creates atomic lines file object containing only one atom
        fatoms2 = pyfant.FileAtoms()
        fatoms2.atoms = [atom]

        ecombo = pyfant.Combo()
        # Overrides file "atoms.dat" with in-memory object
        ecombo.conf.file_atoms = fatoms2
        ecombo.conf.flag_output_to_dir = True
        oo = ecombo.conf.opt
Example #3
0
a99.logging_level = logging.INFO
a99.flag_log_file = True


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
     description=__doc__,
     formatter_class=a99.SmartFormatter
     )
    parser.add_argument('llzero', type=float, nargs=1,
     help='lower wavelength boundary (angstrom)')
    parser.add_argument('llfin', type=float, nargs=1,
     help='upper wavelength boundary (angstrom)')
    parser.add_argument('fn_input', type=str, help='input file name', nargs=1)
    parser.add_argument('fn_output', type=str, help='output file name', nargs=1)

    args = parser.parse_args()

    file_atoms = pyfant.FileAtoms()
    file_atoms.load(args.fn_input[0])

    m = min([min(a.lambda_) for a in file_atoms.atoms])
    M = max([max(a.lambda_) for a in file_atoms.atoms])

    print("Original interval: [%g, %g]" % (m, M))
    print("New interval: [%g, %g]" % (args.llzero[0], args.llfin[0]))

    file_atoms.cut(args.llzero[0], args.llfin[0])
    file_atoms.save_as(args.fn_output[0])
    print("Successfully created file '%s'" % args.fn_output[0])
Example #4
0
def vald3_to_atoms(file_obj):
    """
    Converts data from a VALD3 file into a FileAtoms object.

    Args:
      file_obj: file-like object, e.g., returned by open()

    Returns: a FileAtoms object

    VALD3 website: http://vald.astro.uu.se/
    """

    _logger = a99.get_python_logger()

    def log_skipping(r, reason, row):
        _logger.info("Skipping row #%d (%s)" % (r, reason))
        _logger.info(str(row))

    reader = csv.reader(file_obj)
    ret = pyfant.FileAtoms()
    edict = {
    }  # links atomic symbols with Atom objects created (key is atomic symbol)
    r = 0
    num_skip_ioni, num_skip_mol = 0, 0
    try:
        for row in reader:
            r += 1
            if len(row) <= 12:  # Condition to detect row of interest
                continue

            elem = row[0][1:row[0].index(" ")]
            if not elem in _Symbols:
                # skips molecule
                num_skip_mol += 1
                continue

            # # Collects information and creates atomic line object.
            # Note: Variable names follow Fortran source variable names.

            s_ioni = row[0][-2]
            ioni = int(s_ioni)  # not used, stays as file validation

            if ioni > 2:
                # log_skipping(r, "ionization > 2", row)
                num_skip_ioni += 1
                continue

            _waals = float(row[12])
            if _waals > 0:
                # If the van der Waals damping parameter is > 0, it means
                # something else, see the documentation at
                # http://www.astro.uu.se/valdwiki/Vald3Format:
                #  "if >0 : two parameters as defined in Barklem et al.
                #   2000A&AS..142..467B : integer part is cross-section sigma,
                #   fractional part is velocity parameter alpha"
                # Therefore, we fall back.
                _waals = 0

            line = pyfant.AtomicLine()
            line.lambda_ = float(row[1])
            line.algf = float(row[2])
            line.kiex = float(row[3])
            if _waals == 0:
                line.ch = 0.3e-31
            else:
                try:
                    # Formula supplied by Elvis Cantelli:
                    # extracted from cross-entropy code by P. Barklem
                    line.ch = 10**(2.5 * _waals - 12.32)
                except:
                    # Catches error to log _waals value that gave rise to error
                    _logger.critical("Error calculating ch: waals=%g" % _waals)
                    raise

            # Setting gr to zero will cause PFANT to calculate it using a formula.
            # See pfantlib.f90::read_atoms() for the formula.
            line.gr = 0.0
            # ge is not present in VALD3 file.
            # it enters as a multiplicative term in popadelh(). The original
            # atom4070g.dat and atoms.dat all had ge=0 for all lines.
            line.ge = 0.0
            # Attention: zinf must be tuned later using tune-zinf.py
            line.zinf = 0.5
            # Never used in PFANT
            line.abondr = 1

            # # Stores line in object
            elem = pyfant.adjust_atomic_symbol(elem)
            key = elem + s_ioni  # will group elements by this key
            if key in edict:
                a = edict[key]
            else:
                a = edict[key] = pyfant.Atom()
                a.elem = elem
                a.ioni = int(s_ioni)
                ret.atoms.append(a)
            a.lines.append(line)
    except Exception as e:
        raise type(e)(("Error around %d%s row of VALD3 file" %
                       (r, a99.ordinal_suffix(r))) + ": " +
                      str(e)).with_traceback(sys.exc_info()[2])
    _logger.debug("VALD3-to-atoms conversion successful!")
    _logger.info("Number of lines skipped (molecules): %d" % num_skip_mol)
    _logger.info("Number of lines skipped (ioni > 2): %d" % num_skip_ioni)
    _logger.debug("Number of (element+ioni): %s" % len(ret))
    _logger.debug("Total number of atomic lines: %d" %
                  (sum(len(a) for a in ret.atoms), ))
    return ret
Example #5
0
def turbospectrum_to_atoms(file_obj):
    """
    Converts data from a TurboSpectrum file into a FileAtoms object.

    Args:
      file_obj: file-like object, e.g., returned by open()

    Returns: a FileAtoms object
    """

    _logger = a99.get_python_logger()

    def log_skipping(r, reason, row):
        _logger.info("Skipping row #%d (%s)" % (r, reason))
        _logger.info(str(row))

    ret = pyfant.FileAtoms()
    edict = {}  # links atomic symbols with Atom objects created (key is atomic symbol + ionization)
    r = 0  # number of current row
    num_skip_ioni, num_skip_mol = 0, 0
    state = _X_EL0
    try:
        for row in file_obj:
            r += 1

            if state < _X_LINE_OR_EL0:
                if row[0] != "'":
                    raise ParseError("Expecting element specification, but found something else")

            if state == _X_EL0:
                #' 3.000              '    1       110
                #0123456
                elem = _Symbols[int(row[1:3])]
                ioni = int(row[4:7])+1
                state = _X_EL1
            elif state == _X_EL1:
                state = _X_LINE_OR_EL0
            elif state == _X_LINE_OR_EL0:
                if row[0] == "'":
                    elem = _Symbols[int(row[1:3])]
                    ioni = int(row[4:7]) + 1
                    state = _X_EL1
                else:
                    if ioni > 2:
                        # log_skipping(r, "ionization > 2", row)
                        num_skip_ioni += 1
                        continue

                    #'Li I '
                    #  4601.843  1.848  -5.804  2.50    6.0  5.01E+07 'p' 'f'   0.0    1.0 'Li I    2p  2P    4f  2F     SEN    '
                    #0         1         2         3
                    #01234567890123456789012345678901234567890

                    rr = row.split()

                    _waals = float(rr[3])
                    if _waals > 0:
                        _waals = 0

                    line = pyfant.AtomicLine()
                    line.lambda_ = float(rr[0])
                    line.kiex = float(rr[1])
                    line.algf = float(rr[2])
                    if _waals == 0:
                        line.ch = 0.3e-31
                    else:
                        try:
                            # Formula supplied by Elvis Cantelli:
                            # extracted from cross-entropy code by P. Barklem
                            line.ch = 10**(2.5*_waals-12.32)
                        except:
                            # Catches error to log _waals value that gave rise to error
                            _logger.critical("Error calculating ch: waals=%g" % _waals)
                            raise

                    # Setting gr to zero will cause PFANT to calculate it using a formula.
                    # See pfantlib.f90::read_atoms() for the formula.
                    line.gr = 0.0
                    # ge is not present in VALD3 file.
                    # it enters as a multiplicative term in popadelh(). The original
                    # atom4070g.dat and atoms.dat all had ge=0 for all lines.
                    line.ge = 0.0
                    # Attention: zinf must be tuned later using tune-zinf.py
                    line.zinf = 0.5
                    # Never used in PFANT
                    line.abondr = 1

                    key = f"{elem:2}{ioni:1}"  # will group elements by this key
                    if key in edict:
                        a = edict[key]
                    else:
                        a = edict[key] = pyfant.Atom()
                        a.elem = pyfant.adjust_atomic_symbol(elem)
                        a.ioni = ioni
                        ret.atoms.append(a)
                    a.lines.append(line)

    except Exception as e:
        raise type(e)(("Error around %d%s row of TurboSpectrum file" %
            (r, a99.ordinal_suffix(r)))+": "+str(e)).with_traceback(sys.exc_info()[2])
    _logger.debug("VALD3-to-atoms conversion successful!")
    _logger.info("Number of lines skipped (molecules): %d" % num_skip_mol)
    _logger.info("Number of lines skipped (ioni > 2): %d" % num_skip_ioni)
    _logger.debug("Number of (element+ioni): %s" % len(ret))
    _logger.debug("Total number of atomic lines: %d" % (sum(len(a) for a in ret.atoms),))
    return ret
def synth_plot_build(ax, name=None, st_dt=None):
#takes a name for the synthesis and the star data dictionary
    
    global mainfile
    global abondsfile
    global atomsfile
    
    #initialize main parameters
    mainfile = pf.FileMain()
    mainfile.load()
    mainfile.pas = 0.01
    
    #setting atmospherical parameters
    if pflag or multiflag:
        mainfile.fwhm = st_dt['fwhm']
        teff = st_dt['teff']
        logg = st_dt['logg']
        met = st_dt['met']
        vt = st_dt['vt']
    if fflag:
        mainfile.fwhm = fw
    
    if pflag or multiflag:
        mainfile.titrav = name
        mainfile.teff = teff
        mainfile.glog = logg
        mainfile.asalog = mainfile.afstar = met
        mainfile.vvt = [vt]
        mainfile.flprefix = name[:3]
    mainfile.nhe = 0.085
    mainfile.llzero = linelambda - linerange / 2 - 3
    mainfile.llfin = linelambda + linerange / 2 + 3
    
    #initializing elemental abundance file and values
    #note that if there's a file "abonds.dat" in the directory, it will be used
    #if not, default values (solar) will be loaded
    #additionally, if multirun is being used, the specified abonds file will be used
    abondsfile = pf.FileAbonds()
    if multiflag:
    	abondsfile.load(st_dt['ab_file'])
    else:
    	abondsfile.load()
    idx = abondsfile.ele.index(pf.adjust_atomic_symbol(element))
    if pf.adjust_atomic_symbol(element) != "FE":
        abondsfile.abol[abondsfile.ele.index("FE")] = -99.99
    abondsfile.abol[idx] = -99.99
    
    #initializing atomic data, based on filename passed or not
    atomsfile = pf.FileAtoms()
    atomsfile.load(atomdata)
    
    #setting and interpolating atmospherical model
    m = pf.Innewmarcs()
    m.conf.flag_log_console = False
    m.conf.file_main = mainfile
    m.conf.opt.allow = True
    m.conf.opt.absoru = True
    m.conf.opt.opa = False
    m.run()
    
    #calculating hydrogen lines
    h = pf.Hydro2()
    h.conf.flag_log_console = False
    h.conf.file_main = mainfile
    h.run()
    
    #running pfant only for atoms (except chosen element and Fe)
    spec_atoms = pfant_cut(no_at=False, no_mol=True, fname='only_atoms')
    
    
    #running pfant only for molecules
    spec_molecules = pfant_cut(no_at=True, no_mol=False, fname='only_mols')
    
    #running pfant for separate chosen element lines
    #loading back true abundances
    abondsfile = pf.FileAbonds()
    if multiflag:
    	abondsfile.load(st_dt['ab_file'])
    else:
    	abondsfile.load()
    
    if element != 'Fe':
        el_speclines, el_specval = el_multirun(element)
    
    #running pfant for separate iron lines
    fe_speclines, fe_specval = el_multirun("Fe")
    
    #running pfant for the full spectrum
    spec_full = pfant_cut(no_at=False, no_mol=False, fname='full')
    
    #START PLOTTING
    value_specat = [spec_atoms.x, spec_atoms.y]
    value_specmol = [spec_molecules.x, spec_molecules.y]
    value_total = [spec_full.x, spec_full.y]
    
    ax.plot(value_total[0], value_total[1], 'b-')
    ax.plot(value_specat[0], value_specat[1], 'g-')
    ax.plot(value_specmol[0], value_specmol[1], 'c-')
    
    if sflag or multiflag:
        if multiflag:
            global ospec
            ospec = np.genfromtxt(st_dt['spec'], unpack=True)
            obsplot = ax.plot(ospec[0]+st_dt['sp_adj'][0], ospec[1]/st_dt['sp_adj'][1], 'k--')
        elif rflag:
            ax.plot(ospec[0]+rel[0], ospec[1]/rel[1], 'k--')
        else:
            ax.plot(ospec[0], ospec[1], 'k--')
    for l in fe_specval:
        ax.plot(l[0], l[1], color='#FF8C00', ls='-.', lw=1.5)
    if element != 'Fe':
        for l in el_specval:
            ax.plot(l[0], l[1], 'm-', lw=1.5)
    if multiflag:
    	plt.text(0.04, 0.06, name, horizontalalignment='left', 
    	     	verticalalignment='bottom', fontsize=16,
    	     	transform=plt.gca().transAxes)
    plt.ylim((0., 1.05))
    return [obsplot, ospec]
Example #7
0
"""
Atomic lines file editor
"""

import sys
import argparse
import logging
import a99
import pyfant

a99.logging_level = logging.INFO
a99.flag_log_file = True

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__,
                                     formatter_class=a99.SmartFormatter)
    parser.add_argument('fn',
                        type=str,
                        help='atoms file name',
                        default=pyfant.FileAtoms.default_filename,
                        nargs='?')
    args = parser.parse_args()

    m = pyfant.FileAtoms()
    m.load(args.fn)
    app = a99.get_QApplication([])
    form = pyfant.XFileAtoms()
    form.show()
    form.load(m)
    sys.exit(app.exec_())