Skip to content

Commit 3f10ca9

Browse files
authored
Merge pull request #278 from yucongalicechen/mucalc
compute mu
2 parents e72022e + dd52ad9 commit 3f10ca9

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

Diff for: news/mu.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* function to compute x-ray attenuation coefficient (mu) using XrayDB
4+
5+
**Changed:**
6+
7+
* <news item>
8+
9+
**Deprecated:**
10+
11+
* <news item>
12+
13+
**Removed:**
14+
15+
* <news item>
16+
17+
**Fixed:**
18+
19+
* <news item>
20+
21+
**Security:**
22+
23+
* <news item>

Diff for: requirements/conda.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
numpy
2+
xraydb
23
scipy

Diff for: requirements/pip.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
numpy
2+
xraydb
23
scipy

Diff for: src/diffpy/utils/tools.py

+52
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import numpy as np
77
from scipy.optimize import dual_annealing
88
from scipy.signal import convolve
9+
from xraydb import material_mu
910

1011
from diffpy.utils.parsers.loaddata import loadData
1112

@@ -194,6 +195,57 @@ def get_package_info(package_names, metadata=None):
194195
return metadata
195196

196197

198+
def get_density_from_cloud(sample_composition, mp_token=""):
199+
"""Function to get material density from the MP or COD database.
200+
201+
It is not implemented yet.
202+
"""
203+
raise NotImplementedError(
204+
"So sorry, density computation from composition is not implemented right now. "
205+
"We hope to have this implemented in the next release. "
206+
"Please rerun specifying a sample mass density."
207+
)
208+
209+
210+
def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None, packing_fraction=None):
211+
"""Compute the attenuation coefficient (mu) using the XrayDB database.
212+
213+
Computes mu based on the sample composition and energy.
214+
User should provide a sample mass density or a packing fraction.
215+
If neither density nor packing fraction is specified, or if both are specified, a ValueError will be raised.
216+
Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu.
217+
218+
Parameters
219+
----------
220+
sample_composition : str
221+
The chemical formula of the material.
222+
energy : float
223+
The energy of the incident x-rays in keV.
224+
sample_mass_density : float, optional, Default is None
225+
The mass density of the packed powder/sample in g/cm*3.
226+
packing_fraction : float, optional, Default is None
227+
The fraction of sample in the capillary (between 0 and 1).
228+
Specify either sample_mass_density or packing_fraction but not both.
229+
230+
Returns
231+
-------
232+
mu : float
233+
The attenuation coefficient mu in mm^{-1}.
234+
"""
235+
if (sample_mass_density is None and packing_fraction is None) or (
236+
sample_mass_density is not None and packing_fraction is not None
237+
):
238+
raise ValueError(
239+
"You must specify either sample_mass_density or packing_fraction, but not both. "
240+
"Please rerun specifying only one."
241+
)
242+
if packing_fraction is not None:
243+
sample_mass_density = get_density_from_cloud(sample_composition) * packing_fraction
244+
energy_eV = energy * 1000
245+
mu = material_mu(sample_composition, energy_eV, density=sample_mass_density, kind="total") / 10
246+
return mu
247+
248+
197249
def _top_hat(z, half_slit_width):
198250
"""Create a top-hat function, return 1.0 for values within the specified
199251
slit width and 0 otherwise."""

Diff for: tests/test_tools.py

+30
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from diffpy.utils.tools import (
1010
_extend_z_and_convolve,
1111
check_and_build_global_config,
12+
compute_mu_using_xraydb,
1213
compute_mud,
1314
get_package_info,
1415
get_user_info,
@@ -169,6 +170,35 @@ def test_get_package_info(monkeypatch, inputs, expected):
169170
assert actual_metadata == expected
170171

171172

173+
@pytest.mark.parametrize(
174+
"inputs",
175+
[
176+
# Test when the function has invalid inputs
177+
( # C1: Both mass density and packing fraction are provided, expect ValueError exception
178+
{
179+
"sample_composition": "SiO2",
180+
"energy": 10,
181+
"sample_mass_density": 2.65,
182+
"packing_fraction": 1,
183+
}
184+
),
185+
( # C2: None of mass density or packing fraction are provided, expect ValueError exception
186+
{
187+
"sample_composition": "SiO2",
188+
"energy": 10,
189+
}
190+
),
191+
],
192+
)
193+
def test_compute_mu_using_xraydb_bad(inputs):
194+
with pytest.raises(
195+
ValueError,
196+
match="You must specify either sample_mass_density or packing_fraction, but not both. "
197+
"Please rerun specifying only one.",
198+
):
199+
compute_mu_using_xraydb(**inputs)
200+
201+
172202
def test_compute_mud(tmp_path):
173203
diameter, slit_width, z0, I0, mud, slope = 1, 0.1, 0, 1e5, 3, 0
174204
z_data = np.linspace(-1, 1, 50)

0 commit comments

Comments
 (0)