Skip to content

Commit d2d6371

Browse files
feat: initial commit on getmud module
1 parent 89de7c2 commit d2d6371

File tree

3 files changed

+156
-0
lines changed

3 files changed

+156
-0
lines changed

news/getmud.rst

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* Functionalities to estimate sample mass density or capillary diameter from muD and related chemical info.
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>

src/diffpy/labpdfproc/getmud.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import numpy as np
2+
from scipy.optimize import newton
3+
4+
from diffpy.utils.tools import compute_mu_using_xraydb
5+
6+
7+
def estimate_mass_density(mud, diameter, sample_composition, energy):
8+
"""Estimate sample mass density (g/cm^3) from mu*D
9+
using capillary diameter, sample composition, and energy.
10+
11+
Parameters
12+
----------
13+
mud : float
14+
The given product of attenuation coefficient mu
15+
in mm^{-1} and capillary diameter in mm.
16+
diameter : float
17+
The given diameter of the sample capillary in mm.
18+
sample_composition : str
19+
The chemical formula of the material.
20+
energy : float
21+
The energy of the incident x-rays in keV.
22+
23+
Returns
24+
-------
25+
estimated_density : float
26+
The estimated mass density of the packed powder/sample in g/cm^3.
27+
"""
28+
mu = mud / diameter
29+
30+
def residual_density(density):
31+
return np.abs(
32+
compute_mu_using_xraydb(
33+
sample_composition, energy, sample_mass_density=density
34+
)
35+
- mu
36+
)
37+
38+
estimated_density = newton(residual_density, x0=1.0, x1=10.0)
39+
return estimated_density
40+
41+
42+
def estimate_diameter(
43+
mud,
44+
sample_composition,
45+
energy,
46+
sample_mass_density=None,
47+
packing_fraction=None,
48+
):
49+
"""Estimate capillary diameter (mm) from mu*D and mu.
50+
51+
Parameters
52+
----------
53+
mud : float
54+
The given product of attenuation coefficient mu
55+
in mm^{-1} and capillary diameter in mm.
56+
sample_composition : str
57+
The chemical formula of the material.
58+
energy : float
59+
The energy of the incident x-rays in keV.
60+
sample_mass_density : float
61+
The mass density of the packed powder/sample in g/cm^3.
62+
packing_fraction : float, optional, Default is None
63+
The fraction of sample in the capillary (between 0 and 1).
64+
Specify either sample_mass_density or packing_fraction but not both.
65+
66+
Returns
67+
-------
68+
diameter : float
69+
The given diameter of the sample capillary in mm.
70+
"""
71+
mu = compute_mu_using_xraydb(
72+
sample_composition, energy, sample_mass_density, packing_fraction
73+
)
74+
return mud / mu

tests/test_getmud.py

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import pytest
2+
3+
from diffpy.labpdfproc.getmud import estimate_diameter, estimate_mass_density
4+
5+
6+
@pytest.mark.parametrize(
7+
"inputs, expected_mass_density",
8+
[
9+
(
10+
{
11+
"mud": 2.0,
12+
"diameter": 1.5,
13+
"sample_composition": "ZrO2",
14+
"energy": 20,
15+
},
16+
0.25,
17+
),
18+
],
19+
)
20+
def test_estimate_mass_density(inputs, expected_mass_density):
21+
actual_mass_density = estimate_mass_density(
22+
inputs["mud"],
23+
inputs["diameter"],
24+
inputs["sample_composition"],
25+
inputs["energy"],
26+
)
27+
assert actual_mass_density == pytest.approx(
28+
expected_mass_density, rel=0.01, abs=0.1
29+
)
30+
31+
32+
@pytest.mark.parametrize(
33+
"inputs, expected_diameter",
34+
[
35+
( # C1: user specifies a sample mass density
36+
{
37+
"mud": 2.0,
38+
"sample_composition": "ZrO2",
39+
"energy": 20,
40+
"sample_mass_density": 0.25,
41+
},
42+
1.5,
43+
),
44+
# ( # C2: user specifies a packing fraction
45+
# {
46+
# "mud": 2.0,
47+
# "sample_composition": "ZrO2",
48+
# "energy": 20,
49+
# "packing_fraction": 0.3
50+
# },
51+
# 1.5
52+
# ),
53+
],
54+
)
55+
def test_estimate_diameter(inputs, expected_diameter):
56+
actual_diameter = estimate_diameter(**inputs)
57+
assert actual_diameter == pytest.approx(
58+
expected_diameter, rel=0.01, abs=0.1
59+
)

0 commit comments

Comments
 (0)