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
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]
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)
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])
def __setitem__(self, ele, abol): import pyfant as pf i = self.ele.index(pf.adjust_atomic_symbol(ele)) self.abol[i] = abol
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]
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'])