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
"""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
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])
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
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]
""" 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_())