Skip to content

Commit 23f6598

Browse files
feat: add function and tests to get material density from COD
1 parent a51b553 commit 23f6598

File tree

5 files changed

+84
-11
lines changed

5 files changed

+84
-11
lines changed

news/getdensity.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
**Added:**
2+
3+
* Function to get material density from the COD database.
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>

requirements/conda.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
numpy
22
xraydb
33
scipy
4+
pymatgen

requirements/pip.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
numpy
22
xraydb
33
scipy
4+
pymatgen

src/diffpy/utils/tools.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pathlib import Path
55

66
import numpy as np
7+
from pymatgen.ext.cod import COD
78
from scipy.optimize import dual_annealing
89
from scipy.signal import convolve
910
from xraydb import material_mu
@@ -214,21 +215,48 @@ def get_package_info(package_names, metadata=None):
214215
return metadata
215216

216217

217-
def get_density_from_cloud(sample_composition, mp_token=""):
218-
"""Function to get material density from the MP or COD database.
218+
def get_density_from_cloud(sample_composition, phase=None):
219+
"""Fetch material density from the COD database.
219220
220-
It is not implemented yet.
221+
Parameters
222+
----------
223+
sample_composition : str
224+
The chemical formula of the material.
225+
phase : str, optional, default is None
226+
The phase of the material.
227+
228+
Returns
229+
-------
230+
density : float
231+
Material density in g/cm^3.
221232
"""
222-
raise NotImplementedError(
223-
"So sorry, density computation from composition is not implemented "
224-
"right now. "
225-
"We hope to have this implemented in the next release. "
226-
"Please rerun specifying a sample mass density."
233+
results = COD().get_structure_by_formula(sample_composition)
234+
if phase:
235+
phase = phase.replace(" ", "").lower()
236+
for r in results:
237+
if r.get("sg", "unknown").replace(" ", "").lower() == phase:
238+
return r["structure"].density
239+
print(
240+
"No phase specified. Returning density of the first result. "
241+
"Available densities and phases are:"
227242
)
243+
result_list = [
244+
{
245+
"Density (g/cm^3)": r["structure"].density,
246+
"Phase": r.get("sg", "Unknown").replace(" ", ""),
247+
}
248+
for r in results
249+
]
250+
print(result_list)
251+
return results[0]["structure"].density
228252

229253

230254
def compute_mu_using_xraydb(
231-
sample_composition, energy, sample_mass_density=None, packing_fraction=None
255+
sample_composition,
256+
energy,
257+
sample_mass_density=None,
258+
packing_fraction=None,
259+
phase=None,
232260
):
233261
"""Compute the attenuation coefficient (mu) using the XrayDB database.
234262
@@ -245,10 +273,14 @@ def compute_mu_using_xraydb(
245273
energy : float
246274
The energy of the incident x-rays in keV.
247275
sample_mass_density : float, optional, Default is None
248-
The mass density of the packed powder/sample in g/cm*3.
276+
The mass density of the packed powder/sample in g/cm^3.
249277
packing_fraction : float, optional, Default is None
250278
The fraction of sample in the capillary (between 0 and 1).
251279
Specify either sample_mass_density or packing_fraction but not both.
280+
phase : string, optional, Default is None
281+
The phase information for the sample composition.
282+
Only relevant if you need to fetch the theoretical density
283+
based on the packing fraction.
252284
253285
Returns
254286
-------
@@ -265,7 +297,8 @@ def compute_mu_using_xraydb(
265297
)
266298
if packing_fraction is not None:
267299
sample_mass_density = (
268-
get_density_from_cloud(sample_composition) * packing_fraction
300+
get_density_from_cloud(sample_composition, phase=phase)
301+
* packing_fraction
269302
)
270303
energy_eV = energy * 1000
271304
mu = (

tests/test_tools.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
check_and_build_global_config,
1212
compute_mu_using_xraydb,
1313
compute_mud,
14+
get_density_from_cloud,
1415
get_package_info,
1516
get_user_info,
1617
)
@@ -270,6 +271,20 @@ def test_get_package_info(monkeypatch, inputs, expected):
270271
assert actual_metadata == expected
271272

272273

274+
@pytest.mark.parametrize(
275+
"inputs, expected_density",
276+
[
277+
({"sample_composition": "CeO2"}, 7.2307927),
278+
({"sample_composition": "CeO2", "phase": "P1"}, 7.4143654),
279+
],
280+
)
281+
def test_get_density_from_cloud(inputs, expected_density):
282+
actual_density = get_density_from_cloud(**inputs)
283+
assert actual_density == pytest.approx(
284+
expected_density, rel=1e-4, abs=1e-6
285+
)
286+
287+
273288
@pytest.mark.parametrize(
274289
"inputs",
275290
[

0 commit comments

Comments
 (0)