""" @package pmsco.elements.bindingenergy electron binding energies of the elements extends the element table of the `periodictable` package (https://periodictable.readthedocs.io/en/latest/index.html) by the electron binding energies. the binding energies are compiled from Gwyn Williams' web page (https://userweb.jlab.org/~gwyn/ebindene.html). please refer to the original web page or the x-ray data booklet for original sources, definitions and remarks. binding energies of gases are replaced by respective values of a common compound from the 'handbook of x-ray photoelectron spectroscopy' (physical electronics, inc., 1995). usage ----- this module requires the periodictable package (https://pypi.python.org/pypi/periodictable). ~~~~~~{.py} import periodictable as pt import pmsco.elements.bindingenergy # read any periodictable's element interfaces, e.g. print(pt.gold.binding_energy['4f7/2']) print(pt.elements.symbol('Au').binding_energy['4f7/2']) print(pt.elements.name('gold').binding_energy['4f7/2']) print(pt.elements[79].binding_energy['4f7/2']) ~~~~~~ note that attributes are writable. you may assign refined values in your instance of the database. the query_binding_energy() function queries all terms with a particular binding energy. @author Matthias Muntwiler @copyright (c) 2020 by Paul Scherrer Institut @n Licensed under the Apache License, Version 2.0 (the "License"); @n you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 """ import json import numpy as np import os import periodictable as pt from pmsco.compat import open index_energy = np.zeros(0) index_number = np.zeros(0) index_term = [] default_data_path = os.path.join(os.path.dirname(__file__), "bindingenergy.json") def load_data(data_path=None): """ load binding energy data from json file the data file must be in the same format as generated by save_data. @param file path of the data file. default: "bindingenergy.json" next to this module file @return dictionary """ if data_path is None: data_path = default_data_path with open(data_path) as fp: data = json.load(fp) return data def save_data(data_path=None): """ save binding energy data to json file @param file path of the data file. default: "bindingenergy.json" next to this module file @return None """ if data_path is None: data_path = default_data_path data = {} for element in pt.elements: element_data = {} for term, energy in element.binding_energy.items(): element_data[term] = energy if element_data: data[element.number] = element_data with open(data_path, 'w', 'utf8') as fp: json.dump(data, fp, sort_keys=True, indent='\t') def init(table, reload=False): if 'binding_energy' in table.properties and not reload: return table.properties.append('binding_energy') pt.core.Element.binding_energy = {} pt.core.Element.binding_energy_units = "eV" data = load_data() for el_key, el_data in data.items(): try: el = table[int(el_key)] except ValueError: el = table.symbol(el_key) el.binding_energy = el_data def build_index(): """ build an index for query_binding_energy(). the index is kept in global variables of the module. @return None """ global index_energy global index_number global index_term n = 0 for element in pt.elements: n += len(element.binding_energy) index_energy = np.zeros(n) index_number = np.zeros(n) index_term = [] for element in pt.elements: for term, energy in element.binding_energy.items(): index_term.append(term) i = len(index_term) - 1 index_energy[i] = energy index_number[i] = element.number def query_binding_energy(energy, tol=1.0): """ search the periodic table for a specific binding energy and return all matching terms. @param energy: binding energy in eV. @param tol: tolerance in eV. @return: list of dictionaries containing element and term specification. the list is ordered arbitrarily. each dictionary contains the following keys: @arg 'number': element number @arg 'symbol': element symbol @arg 'term': spectroscopic term @arg 'energy': actual binding energy """ if len(index_energy) == 0: build_index() sel = np.abs(index_energy - energy) < tol idx = np.where(sel) result = [] for i in idx[0]: el_num = int(index_number[i]) d = {'number': el_num, 'symbol': pt.elements[el_num].symbol, 'term': index_term[i], 'energy': index_energy[i]} result.append(d) return result def export_flat_text(f): """ export the binding energies to a flat general text file. the file has four space-separated columns `number`, `symbol`, `term`, `energy`. column names are included in the first row. @param f: file path or open file object @return: None """ if hasattr(f, "write") and callable(f.write): f.write("number symbol term energy\n") for element in pt.elements: for term, energy in element.binding_energy.items(): f.write(f"{element.number} {element.symbol} {term} {energy}\n") else: with open(f, "w") as fi: export_flat_text(fi) def import_flat_text(f): """ import binding energies from a flat general text file. data is in space-separated columns. the first row contains column names. at least the columns `number`, `term`, `energy` must be present. the function updates existing entries and appends entries of non-existing terms. existing terms that are not listed in the file remain unchanged. @param f: file path or open file object @return: None """ data = np.atleast_1d(np.genfromtxt(f, names=True, dtype=None, encoding="utf8")) for d in data: pt.elements[d['number']].binding_energy[d['term']] = d['energy']