Skip to content

Commit

Permalink
Merge pull request #278 from yucongalicechen/mucalc
Browse files Browse the repository at this point in the history
compute mu
  • Loading branch information
sbillinge authored Dec 30, 2024
2 parents e72022e + dd52ad9 commit 3f10ca9
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 0 deletions.
23 changes: 23 additions & 0 deletions news/mu.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**Added:**

* function to compute x-ray attenuation coefficient (mu) using XrayDB

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
1 change: 1 addition & 0 deletions requirements/conda.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
numpy
xraydb
scipy
1 change: 1 addition & 0 deletions requirements/pip.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
numpy
xraydb
scipy
52 changes: 52 additions & 0 deletions src/diffpy/utils/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import numpy as np
from scipy.optimize import dual_annealing
from scipy.signal import convolve
from xraydb import material_mu

from diffpy.utils.parsers.loaddata import loadData

Expand Down Expand Up @@ -194,6 +195,57 @@ def get_package_info(package_names, metadata=None):
return metadata


def get_density_from_cloud(sample_composition, mp_token=""):
"""Function to get material density from the MP or COD database.
It is not implemented yet.
"""
raise NotImplementedError(
"So sorry, density computation from composition is not implemented right now. "
"We hope to have this implemented in the next release. "
"Please rerun specifying a sample mass density."
)


def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None, packing_fraction=None):
"""Compute the attenuation coefficient (mu) using the XrayDB database.
Computes mu based on the sample composition and energy.
User should provide a sample mass density or a packing fraction.
If neither density nor packing fraction is specified, or if both are specified, a ValueError will be raised.
Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu.
Parameters
----------
sample_composition : str
The chemical formula of the material.
energy : float
The energy of the incident x-rays in keV.
sample_mass_density : float, optional, Default is None
The mass density of the packed powder/sample in g/cm*3.
packing_fraction : float, optional, Default is None
The fraction of sample in the capillary (between 0 and 1).
Specify either sample_mass_density or packing_fraction but not both.
Returns
-------
mu : float
The attenuation coefficient mu in mm^{-1}.
"""
if (sample_mass_density is None and packing_fraction is None) or (
sample_mass_density is not None and packing_fraction is not None
):
raise ValueError(
"You must specify either sample_mass_density or packing_fraction, but not both. "
"Please rerun specifying only one."
)
if packing_fraction is not None:
sample_mass_density = get_density_from_cloud(sample_composition) * packing_fraction
energy_eV = energy * 1000
mu = material_mu(sample_composition, energy_eV, density=sample_mass_density, kind="total") / 10
return mu


def _top_hat(z, half_slit_width):
"""Create a top-hat function, return 1.0 for values within the specified
slit width and 0 otherwise."""
Expand Down
30 changes: 30 additions & 0 deletions tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from diffpy.utils.tools import (
_extend_z_and_convolve,
check_and_build_global_config,
compute_mu_using_xraydb,
compute_mud,
get_package_info,
get_user_info,
Expand Down Expand Up @@ -169,6 +170,35 @@ def test_get_package_info(monkeypatch, inputs, expected):
assert actual_metadata == expected


@pytest.mark.parametrize(
"inputs",
[
# Test when the function has invalid inputs
( # C1: Both mass density and packing fraction are provided, expect ValueError exception
{
"sample_composition": "SiO2",
"energy": 10,
"sample_mass_density": 2.65,
"packing_fraction": 1,
}
),
( # C2: None of mass density or packing fraction are provided, expect ValueError exception
{
"sample_composition": "SiO2",
"energy": 10,
}
),
],
)
def test_compute_mu_using_xraydb_bad(inputs):
with pytest.raises(
ValueError,
match="You must specify either sample_mass_density or packing_fraction, but not both. "
"Please rerun specifying only one.",
):
compute_mu_using_xraydb(**inputs)


def test_compute_mud(tmp_path):
diameter, slit_width, z0, I0, mud, slope = 1, 0.1, 0, 1e5, 3, 0
z_data = np.linspace(-1, 1, 50)
Expand Down

0 comments on commit 3f10ca9

Please sign in to comment.