"""
dabax: python module for processing remote files containing dabax
"""
from typing import Tuple, List, Any
import numpy
import os
from urllib.request import urlretrieve, build_opener, HTTPSHandler, install_opener
from silx.io.specfile import SpecFile
import ssl
from dabax.common_tools import calculate_f0_from_f0coeff, f0_interpolate_coefficients
from dabax.common_tools import atomic_symbols, atomic_names, atomic_number
from dabax.common_tools import parse_formula
try:
# create an "unverified" SSL context
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
# build and install an opener that uses the unverified context for HTTPS
install_opener(build_opener(HTTPSHandler(context=context)))
except:
pass
[docs]class Functions:
"""Registry of DABAX data-file function types used to select parsing mode."""
f0 = "f0"
f1f2 = "f1f2"
CrossSec = "CrossSec"
Crystals = "Crystals"
AtomicWeights = "AtomicWeights"
AtomicConstants = "AtomicConstants"
[docs] @staticmethod
def get_mode(function):
"""Return the parsing mode (0=column, 1=entry) for the given function type."""
return 0 if function in [Functions.f0, Functions.AtomicConstants] else 1
[docs]class DabaxBase(object):
"""
Base class providing access to DABAX data files (local or remote).
Handles downloading, caching, and parsing of SPEC-format DABAX files
for f0, f1f2, cross-sections, crystal structures, and atomic data.
"""
def __init__(self,
dabax_repository=None,
verbose=False,
file_f0="f0_InterTables.dat",
file_f1f2="f1f2_Windt.dat",
file_CrossSec = "CrossSec_EPDL97.dat",
file_Crystals="Crystals.dat",
file_AtomicWeights="AtomicWeights.dat",
file_AtomicConstants="AtomicConstants.dat",
):
"""
Parameters
----------
dabax_repository : str, optional
URL or local path to the DABAX file repository.
Defaults to the official GitHub raw URL.
verbose : bool, optional
Print file access messages.
file_f0 : str, optional
Name of the f0 data file.
file_f1f2 : str, optional
Name of the f1/f2 data file.
file_CrossSec : str, optional
Name of the cross-section data file.
file_Crystals : str, optional
Name of the crystal structures data file.
file_AtomicWeights : str, optional
Name of the atomic weights data file.
file_AtomicConstants : str, optional
Name of the atomic constants data file.
"""
self._dabax_repository = dabax_repository if not dabax_repository is None else self.get_dabax_default_repository()
self._verbose = verbose
self._spec_file_registry = {}
self._modes = {}
self.set_file_f0(file_f0)
self.set_file_f1f2(file_f1f2)
self.set_file_CrossSec(file_CrossSec)
self.set_file_Crystals(file_Crystals)
self.set_file_AtomicWeights(file_AtomicWeights)
self.set_file_AtomicConstants(file_AtomicConstants)
def _register_file(self, filename, function):
spec_file = SpecFile(self.get_dabax_file(filename))
entries = DabaxBase._get_entries(spec_file, Functions.get_mode(function))
self._spec_file_registry[filename] = [spec_file, entries]
return spec_file, entries
def _get_registered_spec_file(self, filename, function):
data = self._spec_file_registry.get(filename, [None, None])
spec_file = data[0]
entries = data[1]
if not spec_file is None: return spec_file, entries
else: return self._register_file(filename, function)
@staticmethod
def _get_index_of_entry(entries: Tuple, entry_name: str) -> int:
try: return entries.index(entry_name)
except: return -1
@staticmethod
def _get_entries(spec_file : SpecFile, mode=0) -> Tuple:
entries = []
for index in range(len(spec_file)):
s1 = spec_file[index]
name = s1.scan_header_dict["S"]
if mode == 0:
try: entries.append(name.split(' ')[1])
except: pass
elif mode == 1:
name = ' '.join(name.split())
try: entries.append(name.split(' ')[1])
except: pass
return entries
@staticmethod
def _get_data_and_labels(spec_file: SpecFile, entries: Tuple, entry_name, verbose=False, filename=None):
index_found = DabaxBase._get_index_of_entry(entries, entry_name)
flag_found = index_found != -1
if not flag_found and verbose:
print("Entry name %s not found in DABAX file: %s" % (entry_name, filename))
return None, None, -1
data = spec_file[index_found].data
labels = spec_file[index_found].labels
return data, labels, index_found
@staticmethod
def _get_interesting_entries(entries: Tuple, symbol: str) -> Tuple[List[Any], List[Any], List[Any]]:
interesting_entries = []
charge_list = []
index_list = []
for i, entry in enumerate(entries):
if entry.find(symbol) == 0:
if entry == symbol:
interesting_entries.append(entry)
charge_list.append(0.0)
index_list.append(i)
else:
entry2 = entry.replace(symbol, '')
try:
charge_item = int(entry2[::-1]) # convert to integer the reversed string
charge_list.append(charge_item)
interesting_entries.append(entry)
index_list.append(i)
except:
pass
return charge_list, index_list, interesting_entries
@staticmethod
def _get_coefficient_list(spec_file: SpecFile, index_list: Tuple[int]):
return [spec_file[i].data[:, 0] for i in index_list]
[docs] def get_dabax_default_repository(self):
"""Return the default remote DABAX repository URL."""
return "https://raw.githubusercontent.com/oasys-kit/DabaxFiles/main/"
[docs] def set_dabax_repository(self, repo):
"""Set the DABAX repository URL or local path."""
self._dabax_repository = repo
[docs] def get_dabax_repository(self):
"""Return the current DABAX repository URL or local path."""
return self._dabax_repository
[docs] def set_verbose(self, value=True):
"""Enable or disable verbose output."""
self._verbose = value
[docs] def verbose(self):
"""Return the verbose flag."""
return self._verbose
[docs] def set_file_f0(self, filename):
"""Set and register the f0 data file."""
self._file_f0 = filename
self._sf_f0, self._sf_f0_entries = self._register_file(self._file_f0, Functions.f0)
[docs] def get_file_f0(self):
"""Return the current f0 data file name."""
return self._file_f0
[docs] def set_file_f1f2(self, filename):
"""Set and register the f1/f2 data file."""
self._file_f1f2 = filename
self._sf_f1f2, self._sf_f1f2_entries = self._register_file(self._file_f1f2, Functions.f1f2)
[docs] def get_file_f1f2(self):
"""Return the current f1/f2 data file name."""
return self._file_f1f2
[docs] def set_file_CrossSec(self, filename):
"""Set and register the cross-section data file."""
self._file_CrossSec = filename
self._sf_CrossSec, self._sf_CrossSec_entries = self._register_file(self._file_CrossSec, Functions.CrossSec)
[docs] def get_file_CrossSec(self):
"""Return the current cross-section data file name."""
return self._file_CrossSec
[docs] def set_file_Crystals(self, filename):
"""Set and register the crystal structures data file."""
self._file_Crystals = filename
self._sf_Crystals, self._sf_Crystals_entries = self._register_file(self._file_Crystals, Functions.Crystals)
[docs] def get_file_Crystals(self):
"""Return the current crystal structures data file name."""
return self._file_Crystals
[docs] def set_file_AtomicWeights(self, filename):
"""Set and register the atomic weights data file."""
self._file_AtomicWeights = filename
self._sf_AtomicWeights, self._sf_AtomicWeights_entries = self._register_file(self._file_AtomicWeights, Functions.AtomicWeights)
[docs] def get_file_AtomicWeights(self) -> str:
"""Return the current atomic weights data file name."""
return self._file_AtomicWeights
[docs] def set_file_AtomicConstants(self, filename):
"""Set and register the atomic constants data file."""
self._file_AtomicConstants = filename
self._sf_AtomicConstants, self._sf_AtomicConstants_entries = self._register_file(self._file_AtomicConstants, Functions.AtomicConstants)
[docs] def get_file_AtomicConstants(self):
"""Return the current atomic constants data file name."""
return self._file_AtomicConstants
[docs] def info(self):
"""Return a formatted string summarising the current DABAX configuration."""
txt = "################ DABAX info ###########\n"
txt += "dabax repository: %s\n" % self.get_dabax_repository()
txt += "dabax f0 file: %s\n" % self.get_file_f0()
txt += "dabax f1f2 file: %s\n" % self.get_file_f1f2()
txt += "dabax CrossSec file: %s\n" % self.get_file_CrossSec()
txt += "dabax Crystals file: %s\n" % self.get_file_Crystals()
txt += "########################################\n"
return txt
[docs] def is_remote(self):
"""Return True if the repository is a remote URL."""
if "http" in self.dabax_repository:
return True
else:
return False
#########################
# common access tools
#########################
[docs] def get_dabax_file(self, filename):
"""
Return the local path to a DABAX file, downloading it first if necessary.
Parameters
----------
filename : str
DABAX file name (e.g. ``"f0_InterTables.dat"``).
Returns
-------
str
Absolute local filesystem path to the file.
"""
#
# file exists in current directory
#
dabax_repository = self.get_dabax_repository()
# Use a default writable directory
filepath = os.path.join(get_dabax_directory(), os.path.basename(filename)) # extra safety
if os.path.exists(filepath):
if self.verbose(): print("Dabax file exists in local directory: %s " % filepath)
return filepath
#
# download remote file
#
if dabax_repository[0:3] == "htt" or dabax_repository[0:3] == "ftp":
try:
filepath, http_msg = urlretrieve(dabax_repository + filename,
filename=filepath,
reporthook=None,
data=None)
if self.verbose(): print("Dabax file %s downloaded from %s" % (filepath, dabax_repository + filename))
wait_until_downloaded(filepath)
return filepath
except:
try: # in case there are write permissions issues
filepath, http_msg = urlretrieve(dabax_repository + filename,
filename=None, # will create a temp file
reporthook=None,
data=None)
if self.verbose(): print("Dabax file %s downloaded from %s" % (filepath, dabax_repository + filename))
wait_until_downloaded(filepath)
return filepath
except:
raise Exception("Failed to download file %s from %s" % (filename, dabax_repository))
#
# file exists in local repository
#
filepath = os.path.join(dabax_repository, filename)
if os.path.exists(filepath):
if self.verbose(): print("Dabax file exists in local directory: %s " % filepath)
return filepath
print("Error trying to access file: %s" % filepath)
raise Exception(FileNotFoundError)
#########################
# f0
#########################
[docs] def get_f0_coeffs_from_dabax_file(self, entry_name="Y3+"):
"""
Return the f0 parametric coefficients for a given element or ion.
Parameters
----------
entry_name : str, optional
Element symbol or ion (e.g. ``"Si"``, ``"Y3+"``). Default ``"Y3+"``.
Returns
-------
numpy.ndarray
Array of f0 coefficients, or empty list if not found.
"""
filename = self.get_file_f0()
spec_file, entries = self._get_registered_spec_file(filename, Functions.f0)
data, _, _ = DabaxBase._get_data_and_labels(spec_file,
entries,
entry_name,
verbose=self.verbose(),
filename=filename)
if not data is None: return data[:, 0]
else: return []
[docs] def f0_with_fractional_charge(self, Z, charge=0.0):
"""
Return f0 coefficients for element Z at a given (possibly fractional) ionic charge.
Parameters
----------
Z : int
Atomic number.
charge : float, optional
Ionic charge. Interpolates between tabulated values when non-integer.
Returns
-------
numpy.ndarray
f0 coefficient array.
"""
symbol = atomic_symbols()[Z]
if charge == 0.0:
return self.get_f0_coeffs_from_dabax_file(entry_name=symbol)
else:
spec_file, entries = self._get_registered_spec_file(self.get_file_f0(), Functions.f0)
charge_list, index_list, _ = DabaxBase._get_interesting_entries(entries, symbol)
return f0_interpolate_coefficients(charge,
charge_list,
DabaxBase._get_coefficient_list[spec_file, index_list])
#
#
#
def _f0_with_fractional_charge_get_entries(self, Z, charge=0.0):
symbol = atomic_symbols()[Z]
if charge == 0.0:
return None
else:
spec_file, entries = self._get_registered_spec_file(self.get_file_f0(), Functions.f0)
charge_list, index_list, interesting_entries = DabaxBase._get_interesting_entries(entries, symbol)
return interesting_entries, charge_list, DabaxBase._get_coefficient_list(spec_file, index_list)
######################
# f1f2
######################
[docs] def f1f2_interpolate(self,
entry_name,
energy,
method=2, # 0: lin-lin, 1=lin-log, 2=log-lin, 3:log-log
):
"""
Interpolate f1/f2 at given photon energy values.
Parameters
----------
entry_name : str
Element symbol or ion.
energy : float or numpy.ndarray
Photon energy in eV.
method : int, optional
Interpolation method: 0=lin-lin, 1=lin-log, 2=log-lin (default), 3=log-log.
Returns
-------
f1_interpolated : float or numpy.ndarray
f2_interpolated : float or numpy.ndarray
"""
energy0, f1, f2 = self.f1f2_extract(entry_name)
if method == 0:
f1_interpolated = numpy.interp(energy, energy0, f1)
f2_interpolated = numpy.interp(energy, energy0, f2)
elif method == 1:
f1_interpolated = 10 ** numpy.interp((energy),
(energy0),
numpy.log10(f1))
f2_interpolated = 10 ** numpy.interp((energy),
(energy0),
numpy.log10(f2))
elif method == 2:
f1_interpolated = numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
f1)
f2_interpolated = numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
f2)
elif method == 3:
f1_interpolated = 10 ** numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
numpy.log10(f1))
f2_interpolated = 10 ** numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
numpy.log10(f2))
else:
raise ValueError(f"Method {method} not recognized")
return f1_interpolated, f2_interpolated
######################
# crosssec
######################
[docs] def crosssec_interpolate(self, entry_name, energy,
method=2, # 0: lin-lin, 1=lin-log, 2=log-lin, 3:log-log
partial='TotalCrossSection[barn/atom]',
):
"""
Interpolate cross-section at given photon energy values.
Parameters
----------
entry_name : str
Element symbol.
energy : float or numpy.ndarray
Photon energy in eV.
method : int, optional
Interpolation method: 0=lin-lin, 1=lin-log, 2=log-lin (default), 3=log-log.
partial : str, optional
Column label for the cross-section type.
Returns
-------
float or numpy.ndarray
Interpolated cross-section value(s).
"""
out = self.crosssec_extract(entry_name, partial=partial)
if out is None: raise Exception("Descriptor %s not in file %s" % (entry_name, self.get_file_CrossSec()))
else: energy0, cs = out
if method == 0:
cs_interpolated = numpy.interp(energy, energy0, cs)
elif method == 1:
cs_interpolated = 10 ** numpy.interp((energy),
(energy0),
numpy.log10(cs))
elif method == 2:
cs_interpolated = numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
cs)
elif method == 3:
cs_interpolated = 10 ** numpy.interp(numpy.log10(energy),
numpy.log10(energy0),
numpy.log10(cs))
else:
raise ValueError(f"Method {method} not recognized")
return cs_interpolated
######################
# miscellaneous
######################
[docs] def atomic_weights(self, descriptor,
filename="AtomicWeights.dat",
):
"""
Return atomic weights from DABAX.
Parameters
----------
descriptor : str or list of str
Element symbol (e.g. ``"Ge"``) or isotope string (e.g. ``"70Ge"``).
If a plain symbol is given, the averaged atomic mass is returned.
If an isotope prefix is given, the mass of that specific isotope is returned.
filename : str, optional
DABAX atomic weights file. Default ``"AtomicWeights.dat"``.
Returns
-------
float or list of float
Atomic weight(s) in atomic mass units.
"""
spec_file, scan_names = self._get_registered_spec_file(filename, Functions.AtomicWeights)
if isinstance(descriptor, str):
descriptor = [descriptor]
descriptor_is_string = 1
else: # is list
descriptor_is_string = 0
out = []
for idescriptor in descriptor:
flag_found = False
index_found = []
for index, scan_name in enumerate(scan_names):
if scan_name[-len(idescriptor):] == idescriptor:
flag_found = True
index_found.append(index)
if not flag_found: raise (Exception("Entry name not found: %s" % idescriptor))
data = spec_file[index_found[0]].data
if idescriptor[0].isdigit(): out.append(data[0, 0])
else: out.append(data[2, 0])
if descriptor_is_string: return out[0]
else: return out
[docs] def atomic_constants(self, descriptor,
filename="AtomicConstants.dat",
return_item=0,
return_label=None,
):
"""
Return atomic constants from DABAX.
Parameters
----------
descriptor : str or list of str
Element symbol or list of symbols (e.g. ``"Si"`` or ``["Si", "Fe"]``).
filename : str, optional
DABAX atomic constants file. Default ``"AtomicConstants.dat"``.
return_item : int, optional
Column index to return (0–11). Used when ``return_label`` is None.
return_label : str, optional
Name of the quantity to return. Takes priority over ``return_item``.
Accepted values: ``'AtomicRadius'``, ``'CovalentRadius'``,
``'AtomicMass'``, ``'BoilingPoint'``, ``'MeltingPoint'``,
``'Density'``, ``'AtomicVolume'``, ``'CoherentScatteringLength'``,
``'IncoherentX-section'``, ``'Absorption@1.8A'``,
``'DebyeTemperature'``, ``'ThermalConductivity'``.
Returns
-------
float or list of float
Value(s) of the requested atomic constant.
Examples
--------
>>> dx.atomic_constants('Si', return_label='AtomicMass')
28.0855
"""
if isinstance(descriptor, str):
descriptor = [descriptor]
descriptor_is_string = 1
else: # is list
descriptor_is_string = 0
return_index = -1
if return_label is None:
return_index = return_item
else:
if return_label == 'AtomicRadius' : return_index = 0
if return_label == 'CovalentRadius' : return_index = 1
if return_label == 'AtomicMass' : return_index = 2
if return_label == 'BoilingPoint' : return_index = 3
if return_label == 'MeltingPoint' : return_index = 4
if return_label == 'Density' : return_index = 5
if return_label == 'AtomicVolume' : return_index = 6
if return_label == 'CoherentScatteringLength' : return_index = 7
if return_label == 'IncoherentX-section' : return_index = 8
if return_label == 'Absorption@1.8A' : return_index = 9
if return_label == 'DebyeTemperature' : return_index = 10
if return_label == 'ThermalConductivity' : return_index = 11
if return_index == -1: raise Exception("Bad item index")
# access spec file
spec_file, scan_names = self._get_registered_spec_file(filename, Functions.AtomicConstants)
out = []
for idescriptor in descriptor:
index = DabaxBase._get_index_of_entry(scan_names, idescriptor)
flag_found = index != -1
index_found = index
if flag_found: out.append(spec_file[index_found].data[return_index, 0])
else: raise Exception("Data not found for %s " % idescriptor)
if descriptor_is_string: return out[0]
else: return out
[docs] def element_density(self,
descriptor,
filename="AtomicConstants.dat"):
"""
Return the density of an element in g/cm³.
Parameters
----------
descriptor : str or list of str
Element symbol(s).
filename : str, optional
DABAX atomic constants file.
Returns
-------
float or list of float
Density in g/cm³.
"""
return self.atomic_constants(descriptor, filename=filename, return_label="Density")
[docs] def compound_parser(self, descriptor):
"""
Parse a chemical formula and return composition data.
Parameters
----------
descriptor : str
Chemical formula string (e.g. ``"SiO2"``, ``"H2O"``).
Returns
-------
dict
Dictionary with keys: ``nElements``, ``nAtomsAll``, ``Elements``
(list of Z), ``massFractions``, ``nAtoms``, ``molarMass``.
"""
zetas, fatomic = parse_formula(formula=descriptor, verbose=self.verbose())
elements = []
atomic_weight = []
massFractions = []
for i ,z in enumerate(zetas):
symbol = atomic_symbols()[z]
atw = self.atomic_weights(symbol)
elements.append(z)
atomic_weight.append(atw)
massFractions.append(fatomic[i ] *atw)
mweight = 0.0
for i in range(len(fatomic)):
mweight += atomic_weight[i] * fatomic[i]
for i in range(len(massFractions)):
massFractions[i] /= mweight
new_dict = {
"nElements": len(elements),
"nAtomsAll": float(numpy.array(fatomic).sum()),
"Elements" :zetas,
"massFractions": massFractions,
"nAtoms" :fatomic,
"molarMass": mweight,
}
return new_dict
import os
import sys
import time
[docs]def get_dabax_directory():
"""
Return the platform-specific local directory used to cache DABAX files.
Returns
-------
str
Path to the local DABAX cache directory (created if absent).
"""
home = os.path.expanduser("~")
if sys.platform.startswith("win"): base = os.environ.get("LOCALAPPDATA", os.path.join(home, "AppData", "Local"))
elif sys.platform == "darwin": base = os.path.join(home, "Library", "Application Support")
else: base = os.environ.get("XDG_DATA_HOME", os.path.join(home, ".local", "share"))
dabax_directory = os.path.join(base, "Dabax")
os.makedirs(dabax_directory, exist_ok=True)
return dabax_directory
[docs]def wait_until_downloaded(filepath, timeout=60):
"""
Block until a file appears on disk or a timeout is reached.
Parameters
----------
filepath : str
Path to the file to wait for.
timeout : float, optional
Maximum wait time in seconds. Default 60.
Returns
-------
bool
True if the file appeared, False on timeout.
"""
start = time.time()
while True:
if os.path.exists(filepath): return True
if time.time() - start > timeout: return False
time.sleep(0.1)
if __name__ == '__main__':
dx = DabaxBase(dabax_repository="https://gitlab.esrf.fr/srio/dabaxfiles/-/raw/main/")
print(dx.info())
#
# f0
#
if False:
#
# test f0 data for B3+
#
q = numpy.array([0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.5,0.6,0.7,0.8,0.9,1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9])
f0_B3plus = numpy.array([2,1.995,1.979,1.954,1.919,1.875,1.824,1.766,1.703,1.566,1.42,1.274,1.132,0.999,0.877,0.767,0.669,0.582,0.507,0.441,0.384,0.335,0.293,0.256])
#
# plot
#
from srxraylib.plot.gol import plot
plot(q, f0_B3plus,
q, calculate_f0_from_f0coeff(dx.f0_with_fractional_charge(5, 3.0), q),
q, calculate_f0_from_f0coeff(dx.f0_with_fractional_charge(5, 2.8), q),
xtitle=r"q (sin $\theta$ / $\lambda$)", ytitle="f0 [electron units]",
legend=["B3plus original",
"B3plus from f0_with_fractional_charge(5,+3)",
"B3plus from f0_with_fractional_charge(5,+2.8)"],
marker=['+', None, None],
title="")
#
# f0 another test
#
if False:
#
# test f0 data for B3+
#
q = numpy.array(
[0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6,
1.7, 1.8, 1.9])
f0_B3plus = numpy.array(
[2, 1.995, 1.979, 1.954, 1.919, 1.875, 1.824, 1.766, 1.703, 1.566, 1.42, 1.274, 1.132, 0.999, 0.877, 0.767,
0.669, 0.582, 0.507, 0.441, 0.384, 0.335, 0.293, 0.256])
#
# plot
#
from srxraylib.plot.gol import plot
plot(q, f0_B3plus,
q, calculate_f0_from_f0coeff(dx.f0_with_fractional_charge(5, 3.0), q),
q, calculate_f0_from_f0coeff(dx.f0_with_fractional_charge(5, 2.8), q),
xtitle=r"q (sin $\theta$ / $\lambda$)", ytitle="f0 [electron units]",
legend=["B3plus original",
"B3plus from f0_with_fractional_charge(5,+3)",
"B3plus from f0_with_fractional_charge(5,+2.8)"],
marker=['+',None,None],
title="", show=1)
if False:
#
# misc
#
print("Ge, Si: ", dx.atomic_weights(["Ge","Si"]))
print("70Ge: ", dx.atomic_weights("70Ge"))
print(atomic_symbols()[14], atomic_names()[14])
print("Si atomic mass", dx.atomic_constants("Si", return_item=2))
print("Si,Ge atomic mass", dx.atomic_constants(["Si", "Ge"], return_item=2))
print("Si,Co atomic mass", dx.atomic_constants(["Si", "Co"], return_label='AtomicMass'))
print("Z=27", atomic_symbols()[27])
print("Ge Z=%d" % atomic_number("Ge"))
print("Density Si: ", dx.element_density("Si"))
if False:
energy, f1, f2 = dx.f1f2_extract("Si")
energy_i = numpy.linspace(10,15000,200)
f1_i, f2_i = dx.f1f2_interpolate("Si", energy=energy_i)
print(">>>>", energy.shape, f1.shape, f2.shape)
from srxraylib.plot.gol import plot
plot(energy, f1,
energy, f2,
energy_i, f1_i,
energy_i, f2_i,
xlog=True, ylog=True, title="f1f2 Si",
legend=['f1','f2','f1_i','f2_i'],
marker=[None,None,'+','+'],
linestyle=[None,None,'',''])
if False: # used to create f0_xop_with_fractional_charge_data() in common_tools
filename = dx.get_file_f0()
file1 = dx.get_dabax_file(filename)
if self.verbose(): print("Accessing file: %s" % filename)
sf = SpecFile(file1)
for Z in range(1,99):
interesting_entries, charge_list, coefficient_list = dx._f0_with_fractional_charge_get_entries(Z, charge=1)
for i,iel in enumerate(coefficient_list):
coefficient_list[i] = iel.tolist()
print(" a.append({'Z':",Z,",'charge_list':",charge_list,",'coefficient_list':",coefficient_list,"})" )
if False:
from common_tools import f0_xop_with_fractional_charge
print("f0 coeffs for Z=14 charge=1.5 DABAX/common_tools: ",
dx.f0_with_fractional_charge(14, charge=1.5),
f0_xop_with_fractional_charge(14, charge=1.5),)
if False:
energy, cs = dx.crosssec_extract("Si")
energy_i = numpy.linspace(10,15000,200)
cs_i = dx.crosssec_interpolate("Si", energy=energy_i)
print(">>>>", energy.shape, cs.shape)
from srxraylib.plot.gol import plot
plot(energy, cs,
energy_i, cs_i,
xlog=True, ylog=True, title="crosssec Si",
legend=['cs','cs_i'],
marker=[None,'+'],
linestyle=[None,''])
print(">>>> cs of Si at 10 kev %g barn/atom ", dx.crosssec_interpolate("Si", energy=50000.0))