Esempio n. 1
0
 def remove_element(self, elem):
     """Removes given element (any ionization level)."""
     elem = pyfant.adjust_atomic_symbol(elem)
     for i in reversed(list(range(len(self)))):
         atom = self.atoms[i]
         if atom.elem == elem:
             del self.atoms[i]
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
Esempio n. 3
0
    def __getitem__(self, ele):
        """Return abundance given element symbol.

        notes_per_ele may be None if index is beyond len.
        """
        import pyfant as pf
        i = self.ele.index(pf.adjust_atomic_symbol(ele))
        return self.abol[i]
Esempio n. 4
0
    def _update_file_abonds(self):
        errors, warnings = [], []
        o, t = self.f, self.tableWidget
        assert isinstance(t, QTableWidget)
        n = t.rowCount()
        ele, abol, notes_per_ele = [], [], []

        for i in range(n):
            # # Element
            item = t.item(i, 0)
            x = str(item.text()).upper().strip()
            try:
                x = self._validate_element(i, x)
            except Exception as E:
                errors.append(_format_error(i, str(E)))
            ele.append(pyfant.adjust_atomic_symbol(x))
            item.setText(x)

            # # Abundance
            item = t.item(i, 1)
            x = 0
            try:
                x = float((item.text()))
            except Exception as E:
                errors.append(_format_error(i, str(E)))
            abol.append(x)
            item.setText(str(x))

            # # Notes per element (no validation required)
            item = t.item(i, 2)
            x = str((item.text())).strip()
            notes_per_ele.append(x)

        d = self.__default_dissoc
        for elem, cclog in zip(d.elems, d.cclog):
            if elem not in ele and elem != " H":
                warnings.append(
                    "<b>Warning</b>: element \"%s\", required for "
                    "dissociative equilibrium calculation, is missing. "
                    "Abundance adopted for \"%s\" will be %g" %
                    (elem.strip(), elem.strip(), cclog + 12))

        o.ele = ele
        o.abol = abol
        o.notes_per_ele = notes_per_ele
        o.notes = self.textEditNotes.toPlainText()
        self.flag_valid = len(errors) == 0
        emsg = ""
        if len(errors) > 0 or len(warnings) > 0:
            emsg = '<ul><li>' + ("<li>".join(warnings + errors))

        self._set_error_text(emsg)
Esempio n. 5
0
    def _do_load(self, filename):
        """Clears internal lists and loads from file."""

        with open(filename, "r") as h:

            r = 0  # counts rows of file
            edict = {
            }  # links atomic symbols with Atom objects created (key is atomic symbol)
            try:
                while True:
                    line = AtomicLine()

                    # (EE)(I) --whitespace-- (float) --ignored...--
                    temp = a99.str_vector(h)
                    elem, s_ioni = temp[0][:-1], temp[0][-1]
                    line.lambda_ = float(temp[1])
                    elem = pyfant.adjust_atomic_symbol(elem)
                    key = elem + s_ioni  # will gb.py elements by this key
                    if key in edict:
                        a = edict[key]
                    else:
                        a = edict[key] = Atom()
                        a.elem = elem
                        a.ioni = int(s_ioni)
                        self.atoms.append(a)
                    a.lines.append(line)
                    r += 1

                    [line.kiex, line.algf, line.ch, line.gr, line.ge, line.zinf, line.abondr, finrai] = \
                        a99.float_vector(h)
                    r += 1
                    # last element is end-of-file flag "finrai"
                    if finrai == 1:
                        break
            except Exception as e:
                raise type(e)(("Error around %d%s row of file '%s'" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename)) +
                              ": " + str(e)).with_traceback(sys.exc_info()[2])
Esempio n. 6
0
 def __setitem__(self, ele, abol):
     import pyfant as pf
     i = self.ele.index(pf.adjust_atomic_symbol(ele))
     self.abol[i] = abol
Esempio n. 7
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
Esempio n. 8
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]
Esempio n. 10
0
                star_data[st_name]['mark'] = True
            else:
                star_data[st_name]['mark'] = False
else:
    atomdata = "atoms.dat"

################generating line properies for marking
atfil = open(atomdata)
cols = [raw.strip().split() for raw in atfil]
trim = cols
lineprops = []

for n, i in enumerate(trim):
    if (len(i) <= 4):
        el = i[0][:-1]
        if el == pf.adjust_atomic_symbol(element).strip():
            lineprops.append([i[0], i[1], trim[n + 1][0], trim[n + 1][1]])

################plotting
fig = plt.figure()

if multiflag:
    stars = star_data.keys()
    subcode = len(stars)*100
    obsplots = {}
    for n, s in enumerate(stars):
        print('working on '+s)
        if n == 0:
            star_data[s]['subpt'] = fig.add_subplot(subcode+n+11)
        else:
            star_data[s]['subpt'] = fig.add_subplot(subcode+n+11, sharex=star_data[stars[0]]['subpt'])