From 5180eeb379535d6a803f627af819e6b5eb36a5b3 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Thu, 26 Dec 2024 11:47:04 -0500 Subject: [PATCH 01/11] initial commit --- news/mu.rst | 23 +++++++++++++++++++++++ requirements/conda.txt | 1 + requirements/pip.txt | 1 + src/diffpy/utils/tools.py | 25 +++++++++++++++++++++++++ tests/test_tools.py | 8 +++++++- 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 news/mu.rst diff --git a/news/mu.rst b/news/mu.rst new file mode 100644 index 00000000..bbf9cb1a --- /dev/null +++ b/news/mu.rst @@ -0,0 +1,23 @@ +**Added:** + +* function to compute x-ray attenuation coefficient (mu) using XrayDB + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/requirements/conda.txt b/requirements/conda.txt index 24ce15ab..b26085a8 100644 --- a/requirements/conda.txt +++ b/requirements/conda.txt @@ -1 +1,2 @@ numpy +xraydb diff --git a/requirements/pip.txt b/requirements/pip.txt index 24ce15ab..b26085a8 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -1 +1,2 @@ numpy +xraydb diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index a6c30ed3..ca965e22 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -3,6 +3,8 @@ from copy import copy from pathlib import Path +from xraydb import material_mu + def _stringify(obj): """ @@ -131,3 +133,26 @@ def get_package_info(package_names, metadata=None): pkg_info.update({package: importlib.metadata.version(package)}) metadata["package_info"] = pkg_info return metadata + + +def compute_mu_using_xraydb(sample, energy, density=None): + """ + compute mu using the XrayDB database + + Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu + + Parameters + ---------- + sample str + the chemical formula or the name of the material + energy float + the energy in eV + density float or None + material density in gr/cm^3 + + Returns + ------- + the attenuation coefficient mu in mm^{-1} + """ + mu = material_mu(sample, energy, density=density, kind="total") / 10 + return mu diff --git a/tests/test_tools.py b/tests/test_tools.py index cf730ddd..62b1673c 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -5,7 +5,7 @@ import pytest -from diffpy.utils.tools import get_package_info, get_user_info +from diffpy.utils.tools import compute_mu_using_xraydb, get_package_info, get_user_info # def _setup_dirs(monkeypatch, user_filesystem): # home_dir, cwd_dir = user_filesystem.home_dir, user_filesystem.cwd_dir @@ -189,3 +189,9 @@ def test_get_package_info(monkeypatch, inputs, expected): ) actual_metadata = get_package_info(inputs[0], metadata=inputs[1]) assert actual_metadata == expected + + +def test_compute_mu_using_xraydb(): + sample, energy, density = "ZrO2", 17445.362740959618, 1.009 + actual_mu = compute_mu_using_xraydb(sample, energy, density=density) + assert actual_mu == pytest.approx(1.252, rel=1e-4, abs=0.1) From 5ff2c2312de6d4eab46c201327053f86cd64e829 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Dec 2024 16:49:30 +0000 Subject: [PATCH 02/11] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/utils/tools.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index ca965e22..2440abef 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -136,8 +136,7 @@ def get_package_info(package_names, metadata=None): def compute_mu_using_xraydb(sample, energy, density=None): - """ - compute mu using the XrayDB database + """Compute mu using the XrayDB database. Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu From 182622167e58bc704f15efefa890e021f2981449 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Thu, 26 Dec 2024 14:58:40 -0500 Subject: [PATCH 03/11] add packing fraction, add more tests --- src/diffpy/utils/tools.py | 24 +++++++++++++++--------- tests/test_tools.py | 26 ++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index ca965e22..3674401a 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -135,24 +135,30 @@ def get_package_info(package_names, metadata=None): return metadata -def compute_mu_using_xraydb(sample, energy, density=None): +def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fraction=1): """ - compute mu using the XrayDB database + Compute the attenuation coefficient (mu) using the XrayDB database + This function calculates mu based on the sample composition and energy. + If density is not provided, a standard reference density (e.g., 0.987 g/cm^3 for H2O) is used. + User can provide either a measured density or an estimated packing fraction (with a standard density). + It is recommended to specify the density, especially for materials like ZrO2, where it can vary. Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu Parameters ---------- - sample str - the chemical formula or the name of the material - energy float - the energy in eV - density float or None - material density in gr/cm^3 + sample_composition: str + The chemical formula or the name of the material + energy: float + The energy in eV + density: float, optional, Default is None + The mass density of the packed powder/sample in gr/cm^3. If None, a standard density from XrayDB is used. + packing_fraction: float, optional, Default is 1 + The fraction of sample in the capillary (between 0 and 1) Returns ------- the attenuation coefficient mu in mm^{-1} """ - mu = material_mu(sample, energy, density=density, kind="total") / 10 + mu = material_mu(sample_composition, energy, density=density, kind="total") * packing_fraction / 10 return mu diff --git a/tests/test_tools.py b/tests/test_tools.py index 62b1673c..dd70d347 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -191,7 +191,25 @@ def test_get_package_info(monkeypatch, inputs, expected): assert actual_metadata == expected -def test_compute_mu_using_xraydb(): - sample, energy, density = "ZrO2", 17445.362740959618, 1.009 - actual_mu = compute_mu_using_xraydb(sample, energy, density=density) - assert actual_mu == pytest.approx(1.252, rel=1e-4, abs=0.1) +params_mu = [ + # C1: user didn't specify density or packing fraction + ({"sample_composition": "H2O", "energy": 10000, "density": None, "packing_fraction": 1}, 0.5330), + # C2: user specified packing fraction only + ({"sample_composition": "H2O", "energy": 10000, "density": None, "packing_fraction": 0.5}, 0.2665), + # C3: user specified density only + ({"sample_composition": "H2O", "energy": 10000, "density": 0.997, "packing_fraction": 1}, 0.5330), + ({"sample_composition": "H2O", "energy": 10000, "density": 0.4985, "packing_fraction": 1}, 0.2665), + # C4: user specified a standard density and a packing fraction + ({"sample_composition": "H2O", "energy": 10000, "density": 0.997, "packing_fraction": 0.5}, 0.2665), +] + + +@pytest.mark.parametrize("inputs, expected", params_mu) +def test_compute_mu_using_xraydb(inputs, expected): + actual_mu = compute_mu_using_xraydb( + inputs["sample_composition"], + inputs["energy"], + density=inputs["density"], + packing_fraction=inputs["packing_fraction"], + ) + assert actual_mu == pytest.approx(expected, rel=0.01, abs=0.1) From be7c275a66ed254e82f6c772fbee2d21bcea13c2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Dec 2024 20:00:29 +0000 Subject: [PATCH 04/11] [pre-commit.ci] auto fixes from pre-commit hooks --- src/diffpy/utils/tools.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index 3674401a..611048f1 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -136,8 +136,7 @@ def get_package_info(package_names, metadata=None): def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fraction=1): - """ - Compute the attenuation coefficient (mu) using the XrayDB database + """Compute the attenuation coefficient (mu) using the XrayDB database. This function calculates mu based on the sample composition and energy. If density is not provided, a standard reference density (e.g., 0.987 g/cm^3 for H2O) is used. From 9e4bc0dc1173978544be084e80ee182311587ccc Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Thu, 26 Dec 2024 15:27:55 -0500 Subject: [PATCH 05/11] refine docstring and test comments --- src/diffpy/utils/tools.py | 24 +++++++------- tests/test_tools.py | 70 ++++++++++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index 3674401a..9b78dec2 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -136,29 +136,29 @@ def get_package_info(package_names, metadata=None): def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fraction=1): - """ - Compute the attenuation coefficient (mu) using the XrayDB database + """Compute the attenuation coefficient (mu) using the XrayDB database. - This function calculates mu based on the sample composition and energy. + Computes mu based on the sample composition and energy. If density is not provided, a standard reference density (e.g., 0.987 g/cm^3 for H2O) is used. User can provide either a measured density or an estimated packing fraction (with a standard density). It is recommended to specify the density, especially for materials like ZrO2, where it can vary. - Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu + Reference: https://xraypy.github.io/XrayDB/python.html#xraydb.material_mu. Parameters ---------- - sample_composition: str - The chemical formula or the name of the material - energy: float - The energy in eV - density: float, optional, Default is None + sample_composition : str + The chemical formula or the name of the material. + energy : float + The energy in eV. + density : float, optional, Default is None The mass density of the packed powder/sample in gr/cm^3. If None, a standard density from XrayDB is used. - packing_fraction: float, optional, Default is 1 - The fraction of sample in the capillary (between 0 and 1) + packing_fraction : float, optional, Default is 1 + The fraction of sample in the capillary (between 0 and 1). Returns ------- - the attenuation coefficient mu in mm^{-1} + mu : float + The attenuation coefficient mu in mm^{-1}. """ mu = material_mu(sample_composition, energy, density=density, kind="total") * packing_fraction / 10 return mu diff --git a/tests/test_tools.py b/tests/test_tools.py index dd70d347..28850985 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -191,25 +191,63 @@ def test_get_package_info(monkeypatch, inputs, expected): assert actual_metadata == expected -params_mu = [ - # C1: user didn't specify density or packing fraction - ({"sample_composition": "H2O", "energy": 10000, "density": None, "packing_fraction": 1}, 0.5330), - # C2: user specified packing fraction only - ({"sample_composition": "H2O", "energy": 10000, "density": None, "packing_fraction": 0.5}, 0.2665), - # C3: user specified density only - ({"sample_composition": "H2O", "energy": 10000, "density": 0.997, "packing_fraction": 1}, 0.5330), - ({"sample_composition": "H2O", "energy": 10000, "density": 0.4985, "packing_fraction": 1}, 0.2665), - # C4: user specified a standard density and a packing fraction - ({"sample_composition": "H2O", "energy": 10000, "density": 0.997, "packing_fraction": 0.5}, 0.2665), -] - - -@pytest.mark.parametrize("inputs, expected", params_mu) -def test_compute_mu_using_xraydb(inputs, expected): +@pytest.mark.parametrize( + "inputs, expected_mu", + [ + # Test whether the function returns the correct mu + ( # C1: No density or packing fraction provided, expect to compute mu based on standard density + { + "sample_composition": "H2O", + "energy": 10000, + "density": None, + "packing_fraction": 1, + }, + 0.5330, + ), + ( # C2: Packing fraction (=0.5) provided only, expect to return half of mu based on standard density + { + "sample_composition": "H2O", + "energy": 10000, + "density": None, + "packing_fraction": 0.5, + }, + 0.2665, + ), + ( # C3: Density provided only, expect to compute mu based on density + # 1. Standard density provided, expect to return the same mu as C1 + { + "sample_composition": "H2O", + "energy": 10000, + "density": 0.997, + "packing_fraction": 1, + }, + 0.5330, + ), + ( # 2. Lower density for H2O (half of standard), expect to return half of mu based on standard density + { + "sample_composition": "H2O", + "energy": 10000, + "density": 0.4985, + "packing_fraction": 1, + }, + 0.2665, + ), + ( # C4: Both standard density and packing fraction are provided, expect to compute the same mu as C2 + { + "sample_composition": "H2O", + "energy": 10000, + "density": 0.997, + "packing_fraction": 0.5, + }, + 0.2665, + ), + ], +) +def test_compute_mu_using_xraydb(inputs, expected_mu): actual_mu = compute_mu_using_xraydb( inputs["sample_composition"], inputs["energy"], density=inputs["density"], packing_fraction=inputs["packing_fraction"], ) - assert actual_mu == pytest.approx(expected, rel=0.01, abs=0.1) + assert actual_mu == pytest.approx(expected_mu, rel=0.01, abs=0.1) From 0bdbbb48a8c9fff3e9a2c9a715baa04dd08e9164 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Fri, 27 Dec 2024 21:18:59 -0500 Subject: [PATCH 06/11] enforce requirement to specify either density or packing fraction --- src/diffpy/utils/tools.py | 31 +++++++++++---- tests/test_tools.py | 82 ++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index 7144a9bb..d8b59f10 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -1,5 +1,6 @@ import importlib.metadata import json +import warnings from copy import copy from pathlib import Path @@ -210,12 +211,12 @@ def get_package_info(package_names, metadata=None): return metadata -def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fraction=1): +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 can provide a measured density or an estimated packing fraction. - Specifying the density is recommended, though not required for some pure or standard materials. + 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 @@ -223,10 +224,10 @@ def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fr sample_composition : str The chemical formula or the name of the material. energy : float - The energy in keV. - density : float, optional, Default is None + 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 gr/cm^3. - packing_fraction : float, optional, Default is 1 + packing_fraction : float, optional, Default is None The fraction of sample in the capillary (between 0 and 1). Returns @@ -234,5 +235,21 @@ def compute_mu_using_xraydb(sample_composition, energy, density=None, packing_fr mu : float The attenuation coefficient mu in mm^{-1}. """ - mu = material_mu(sample_composition, energy * 1000, density=density, kind="total") * packing_fraction / 10 + 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 sample_mass_density is not None: + mu = material_mu(sample_composition, energy * 1000, density=sample_mass_density, kind="total") / 10 + else: + warnings.warn( + "Warning: Density is set to None if a packing fraction is specified, " + "which may cause errors for some materials. " + "We recommend specifying sample mass density for now. " + "Auto-density calculation is coming soon." + ) + mu = material_mu(sample_composition, energy * 1000, density=None, kind="total") * packing_fraction / 10 return mu diff --git a/tests/test_tools.py b/tests/test_tools.py index 06202cdf..a3363320 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -171,59 +171,61 @@ def test_get_package_info(monkeypatch, inputs, expected): "inputs, expected_mu", [ # Test whether the function returns the correct mu - ( # C1: No density or packing fraction (only for known material), expect to get mu from database + ( # C1: Composition, energy, and mass density provided, expect to get mu based on mass density + # 1. Fully dense mass density + {"sample_composition": "quartz", "energy": 10, "sample_mass_density": 2.65}, + 5.0368, + ), + ( # 2. Measured mass density { - "sample_composition": "H2O", - "energy": 10, + "sample_composition": "ZrO2", + "energy": 17.445, + "sample_mass_density": 1.009, }, - 0.5330, + 1.2522, ), - ( # C2: Packing fraction (=0.5) provided only (only for known material) + ( # C2: Composition, energy, and packing fraction provided, expect to get mu based on packing fraction + # Reuse pattern from C1.1 here { - "sample_composition": "H2O", + "sample_composition": "quartz", "energy": 10, "packing_fraction": 0.5, }, - 0.2665, + 2.5184, ), - ( # C3: Density provided only, expect to compute mu based on it - # 1. Known material + ], +) +def test_compute_mu_using_xraydb(inputs, expected_mu): + actual_mu = compute_mu_using_xraydb(**inputs) + assert actual_mu == pytest.approx(expected_mu, rel=1e-6, abs=1e-4) + + +@pytest.mark.parametrize( + "inputs", + [ + # Test when the function raises ValueError + # C1: Both mass density and packing fraction are provided + ( { - "sample_composition": "H2O", + "sample_composition": "quartz", "energy": 10, - "density": 0.987, - }, - 0.5330, + "sample_mass_density": 2.65, + "packing_fraction": 1, + } ), - ( # 2. Unknown material - { - "sample_composition": "ZrO2", - "energy": 17, - "density": 1.009, - }, - 1.252, - ), - ( # C4: Both density and packing fraction are provided, expect to compute mu based on both - # 1. Known material + # C2: None of mass density or packing fraction are provided + ( { - "sample_composition": "H2O", + "sample_composition": "quartz", "energy": 10, - "density": 0.997, - "packing_fraction": 0.5, - }, - 0.2665, - ), - ( # 2. Unknown material - { - "sample_composition": "ZrO2", - "energy": 17, - "density": 1.009, - "packing_fraction": 0.5, - }, - 0.626, + } ), ], ) -def test_compute_mu_using_xraydb(inputs, expected_mu): - actual_mu = compute_mu_using_xraydb(**inputs) - assert actual_mu == pytest.approx(expected_mu, rel=0.01, abs=0.1) +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) From 00f36ad2ff38985ce74c26563cc13887abd7e735 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Sat, 28 Dec 2024 23:35:37 -0500 Subject: [PATCH 07/11] add notimplementederror --- src/diffpy/utils/tools.py | 29 +++++++++++++++++++---------- tests/test_tools.py | 9 --------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index d8b59f10..e1e7ad0a 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -211,6 +211,14 @@ 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 database. + + It is not implemented yet. + """ + raise NotImplementedError + + def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None, packing_fraction=None): """Compute the attenuation coefficient (mu) using the XrayDB database. @@ -242,14 +250,15 @@ def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None "You must specify either sample_mass_density or packing_fraction, but not both. " "Please rerun specifying only one." ) - if sample_mass_density is not None: - mu = material_mu(sample_composition, energy * 1000, density=sample_mass_density, kind="total") / 10 - else: - warnings.warn( - "Warning: Density is set to None if a packing fraction is specified, " - "which may cause errors for some materials. " - "We recommend specifying sample mass density for now. " - "Auto-density calculation is coming soon." - ) - mu = material_mu(sample_composition, energy * 1000, density=None, kind="total") * packing_fraction / 10 + if packing_fraction is None: + packing_fraction = 1 + try: + sample_mass_density = get_density_from_cloud(sample_composition) * packing_fraction + except NotImplementedError: + warnings.warn( + "Density computation is not implemented right now. " + "Please rerun specifying a sample mass density." + ) + energy_eV = energy * 1000 + mu = material_mu(sample_composition, energy_eV, density=sample_mass_density, kind="total") / 10 return mu diff --git a/tests/test_tools.py b/tests/test_tools.py index a3363320..d02996ca 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -184,15 +184,6 @@ def test_get_package_info(monkeypatch, inputs, expected): }, 1.2522, ), - ( # C2: Composition, energy, and packing fraction provided, expect to get mu based on packing fraction - # Reuse pattern from C1.1 here - { - "sample_composition": "quartz", - "energy": 10, - "packing_fraction": 0.5, - }, - 2.5184, - ), ], ) def test_compute_mu_using_xraydb(inputs, expected_mu): From 255c603a54ccc0d680a8a851308355114663ca6c Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Sun, 29 Dec 2024 15:07:29 -0500 Subject: [PATCH 08/11] refactor: rearrange error msg and docstring, update condition in function --- src/diffpy/utils/tools.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index e1e7ad0a..9c963e14 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -1,6 +1,5 @@ import importlib.metadata import json -import warnings from copy import copy from pathlib import Path @@ -212,11 +211,15 @@ def get_package_info(package_names, metadata=None): def get_density_from_cloud(sample_composition, mp_token=""): - """Function to get material density from the MP database. + """Function to get material density from the MP or COD database. It is not implemented yet. """ - raise NotImplementedError + 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): @@ -250,15 +253,8 @@ def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None "You must specify either sample_mass_density or packing_fraction, but not both. " "Please rerun specifying only one." ) - if packing_fraction is None: - packing_fraction = 1 - try: - sample_mass_density = get_density_from_cloud(sample_composition) * packing_fraction - except NotImplementedError: - warnings.warn( - "Density computation is not implemented right now. " - "Please rerun specifying a sample mass density." - ) + 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 From 5492ad8718b46854c8fc0530e9f1d28be4dba89e Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Sun, 29 Dec 2024 21:08:09 -0500 Subject: [PATCH 09/11] test: remove test for the correct mu, improve test comment for invalid inputs --- tests/test_tools.py | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/tests/test_tools.py b/tests/test_tools.py index d02996ca..d3f7cf16 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -167,35 +167,11 @@ def test_get_package_info(monkeypatch, inputs, expected): assert actual_metadata == expected -@pytest.mark.parametrize( - "inputs, expected_mu", - [ - # Test whether the function returns the correct mu - ( # C1: Composition, energy, and mass density provided, expect to get mu based on mass density - # 1. Fully dense mass density - {"sample_composition": "quartz", "energy": 10, "sample_mass_density": 2.65}, - 5.0368, - ), - ( # 2. Measured mass density - { - "sample_composition": "ZrO2", - "energy": 17.445, - "sample_mass_density": 1.009, - }, - 1.2522, - ), - ], -) -def test_compute_mu_using_xraydb(inputs, expected_mu): - actual_mu = compute_mu_using_xraydb(**inputs) - assert actual_mu == pytest.approx(expected_mu, rel=1e-6, abs=1e-4) - - @pytest.mark.parametrize( "inputs", [ - # Test when the function raises ValueError - # C1: Both mass density and packing fraction are provided + # Test when the function has invalid inputs + # C1: Both mass density and packing fraction are provided, expect ValueError exception ( { "sample_composition": "quartz", @@ -204,7 +180,7 @@ def test_compute_mu_using_xraydb(inputs, expected_mu): "packing_fraction": 1, } ), - # C2: None of mass density or packing fraction are provided + # C2: None of mass density or packing fraction are provided, expect ValueError exception ( { "sample_composition": "quartz", From a4a217d482af895970ea4934745b95fc45bd6497 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Sun, 29 Dec 2024 21:29:17 -0500 Subject: [PATCH 10/11] test: reformat tests --- tests/test_tools.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/test_tools.py b/tests/test_tools.py index d3f7cf16..91bf63bb 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -171,19 +171,17 @@ def test_get_package_info(monkeypatch, inputs, expected): "inputs", [ # Test when the function has invalid inputs - # C1: Both mass density and packing fraction are provided, expect ValueError exception - ( + ( # C1: Both mass density and packing fraction are provided, expect ValueError exception { - "sample_composition": "quartz", + "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 - ( + ( # C2: None of mass density or packing fraction are provided, expect ValueError exception { - "sample_composition": "quartz", + "sample_composition": "SiO2", "energy": 10, } ), From dd52ad9b401eb9475fccfb57ee09297a02bafa58 Mon Sep 17 00:00:00 2001 From: yucongalicechen Date: Sun, 29 Dec 2024 21:48:37 -0500 Subject: [PATCH 11/11] docs: improve docstring --- src/diffpy/utils/tools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/diffpy/utils/tools.py b/src/diffpy/utils/tools.py index c562a2dd..036cc696 100644 --- a/src/diffpy/utils/tools.py +++ b/src/diffpy/utils/tools.py @@ -218,13 +218,14 @@ def compute_mu_using_xraydb(sample_composition, energy, sample_mass_density=None Parameters ---------- sample_composition : str - The chemical formula or the name of the material. + 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 gr/cm^3. + 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 -------