Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .zenodo.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
{
"name":"Tina Bergh"
},
{
"name":"Dieter Weber",
"orcid": "0000-0001-6635-9567",
"affiliation": "Forschungszentrum Jülich"
},
{
"name":"Tomas Ostasevicius"
},
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0>`_
this project tries its best to adhere to
`Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.

Unreleased
==========

Added
-----

- Support for wider range of `CIF atom type symbols
<https://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Iatom_type_symbol.html>`_,
notably element symbol followed by oxidation number as found in CIF files
recently pulled from `ICSD <https://icsd.fiz-karlsruhe.de/>`_ (#245).

2025-06-02 - version 0.7.0
==========================

Expand Down
1 change: 1 addition & 0 deletions diffsims/release_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"Jedrzej Morzy",
"Endre Jacobsen",
"Tina Bergh",
"Dieter Weber",
"Tomas Ostasevicius",
"Eirik Opheim",
]
Expand Down
36 changes: 33 additions & 3 deletions diffsims/structure_factor/atomic_scattering_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# You should have received a copy of the GNU General Public License
# along with diffsims. If not, see <http://www.gnu.org/licenses/>.

import re

import numpy as np

# List of elements Z = 1-118
Expand Down Expand Up @@ -140,6 +142,28 @@
# fmt: on


def get_element(atom_type_symbol):
"""Extract element symbol from _atom_type_symbol CIF key

See https://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Iatom_type_symbol.html
for specification.

Parameters
----------
atom_type_symbol : str
Symbol following the specification of _atom_type_symbol CIF key

Returns
-------

element : str
Alphabetic head of atom_type_symbol, notably without oxidation state.
Usually an element symbol, but not guaranteed by the specification.
"""
reg = "^(?P<element>[A-Za-z]*)"
return re.match(reg, atom_type_symbol).group("element")


def get_atomic_scattering_parameters(element, unit=None):
"""Return the eight atomic scattering parameters a_1-4, b_1-4 for
elements with atomic numbers Z = 1-98 from Table 12.1 in
Expand Down Expand Up @@ -191,20 +215,26 @@ def get_atomic_scattering_parameters(element, unit=None):

def get_element_id_from_string(element_str):
r"""Get periodic element ID for elements :math:`Z` = 1-98 from
one-two letter string.
element symbol.

Parameters
----------
element_str : str
One-two letter string.
String starting with an element symbol, optionally delimited from other
following characters by a non-alphabetic character. Only the element
symbol is evaluated. In particular, compatible with common atom type
symbols in CIF files that often start with an element symbol followed by
e.g. an optional oxidation number, although this is not guaranteed:
https://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Iatom_type_symbol.html

Returns
-------
element_id : int
Integer ID in the periodic table of elements.
"""
element = get_element(element_str)
element2periodic = dict(zip(ELEMENTS[:N_ELEMENTS], np.arange(1, N_ELEMENTS)))
element_id = element2periodic[element_str.lower()]
element_id = element2periodic[element.lower()]
return element_id


Expand Down
5 changes: 4 additions & 1 deletion diffsims/tests/structure_factor/test_structure_factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
space_group=225,
structure=Structure(
lattice=Lattice(3.5236, 3.5236, 3.5236, 90, 90, 90),
atoms=[Atom(xyz=[0, 0, 0], atype="Ni", Uisoequiv=0.006332)],
# Atom specified in a way found in CIF files from ICSD
# See also
# https://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Iatom_type_symbol.html
atoms=[Atom(xyz=[0, 0, 0], atype="Ni0+", Uisoequiv=0.006332)],
),
)
ferrite = Phase(
Expand Down
44 changes: 44 additions & 0 deletions diffsims/tests/utils/test_sim_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import numpy as np
import diffpy

from diffpy.structure import Atom, Lattice, Structure
from orix.crystal_map import Phase


from diffsims.utils.sim_utils import (
get_electron_wavelength,
Expand Down Expand Up @@ -348,3 +351,44 @@ def test_get_kinematical_intensities(default_structure, scattering_params, answe
scattering_params=scattering_params,
)
np.testing.assert_array_almost_equal(i_hkls, ([answer]), decimal=4)


# Copied from Nickel, with unknown element Unobtainium
# Arbitrary strings can be found in CIF files, see
# https://www.iucr.org/__data/iucr/cifdic_html/1/cif_core.dic/Iatom_type_symbol.html
unobtainium = Phase(
space_group=225,
structure=Structure(
lattice=Lattice(3.5236, 3.5236, 3.5236, 90, 90, 90),
# Note that the standard explicitly shows "NiFe" and "dummy"
# as examples
atoms=[Atom(xyz=[0, 0, 0], atype="UnOb", Uisoequiv=0.006332)],
),
)


@pytest.mark.parametrize(
"scattering_params, answer",
[
("lobato", 0.0),
(None, 1.0),
],
)
def test_get_kinematical_intensities_unknown(scattering_params, answer):
latt = unobtainium.structure.lattice
reciprocal_lattice = latt.reciprocal()
reciprocal_radius = 0.2
unique_hkls, multiplicites, g_hkls = get_intensities_params(
reciprocal_lattice, reciprocal_radius
)
g_hkls_array = np.asarray(g_hkls)
# Debatable if this should actually be an error and not just a warning
with pytest.warns(UserWarning, match="not found in scattering parameter library."):
i_hkls = get_kinematical_intensities(
unobtainium.structure,
g_indices=unique_hkls,
g_hkls_array=g_hkls_array,
prefactor=multiplicites,
scattering_params=scattering_params,
)
np.testing.assert_array_almost_equal(i_hkls, ([answer]), decimal=4)
19 changes: 14 additions & 5 deletions diffsims/utils/sim_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@

import collections
import math
from warnings import warn

import diffpy.structure
import numpy as np
from scipy.constants import h, m_e, e, c, pi, mu_0

from diffsims.utils.atomic_scattering_params import ATOMIC_SCATTERING_PARAMS
from diffsims.utils.lobato_scattering_params import ATOMIC_SCATTERING_PARAMS_LOBATO
from diffsims.structure_factor.atomic_scattering_parameters import get_element


__all__ = [
Expand Down Expand Up @@ -194,22 +196,29 @@ def get_vectorized_list_for_atomic_scattering_factors(
dwfactors : numpy.ndarray
Debye-Waller factors for each atom in the structure.
"""

if scattering_params is not None:
scattering_params_dict = get_scattering_params_dict(scattering_params)
else:
scattering_params_dict = {}

n_structures = len(structure)
coeffs = np.empty((n_structures, 5, 2))
coeffs = np.zeros((n_structures, 5, 2))
fcoords = np.empty((n_structures, 3))
occus = np.empty(n_structures)
dwfactors = np.empty(n_structures)
default = np.zeros((5, 2))

for i, site in enumerate(structure):
coeffs[i] = scattering_params_dict.get(site.element, default)
dwfactors[i] = debye_waller_factors.get(site.element, 0)
element = get_element(site.element)
# At least emit a warning if a key is not found.
# Probably better to error out since the simulation will be invalid.
try:
coeffs[i] = scattering_params_dict[element]
except KeyError:
warn(
f"Element {element} from atom type symbol {site.element} not "
"found in scattering parameter library."
)
dwfactors[i] = debye_waller_factors.get(element, 0)
fcoords[i] = site.xyz
occus[i] = site.occupancy

Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
# fmt: off
extra_feature_requirements = {
"doc": [
"numpydoc",
# Restriction due to https://github.com/pyxem/orix/issues/570
"numpydoc != 1.9.0",
"pydata-sphinx-theme",
"sphinx >= 3.0.2",
"sphinx-design",
Expand Down
Loading