213 lines
6.1 KiB
Python
213 lines
6.1 KiB
Python
"""
|
|
@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']
|