-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add the class and a test * add to the beamline files * Fix the expected test spacing values Previously this was hard coded to be a static float in milimeters for some reason, forgot to update this for this PR * Implement crystal metadata for I03 DCM (#870) * Implement crystal metadata for I03 DCM * Make type-checking happy * make d spacing a signal * delete the absent keys test * remove the d spacing calculation * respond to feedback * fix crystal metadata variable namign * convert the types correctly * ruff * apparently this fixes tests and coverage * remove print * remove is None checks --------- Co-authored-by: rtuck99 <[email protected]>
- Loading branch information
Showing
8 changed files
with
197 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import math | ||
from dataclasses import dataclass | ||
from enum import Enum | ||
from typing import Literal | ||
|
||
|
||
@dataclass(frozen=True) | ||
class Material: | ||
""" | ||
Class representing a crystalline material with a specific lattice parameter. | ||
""" | ||
|
||
name: str | ||
lattice_parameter: float # Lattice parameter in meters | ||
|
||
|
||
class MaterialsEnum(Enum): | ||
Si = Material(name="silicon", lattice_parameter=5.4310205e-10) | ||
Ge = Material(name="germanium", lattice_parameter=5.6575e-10) | ||
|
||
|
||
@dataclass(frozen=True) | ||
class CrystalMetadata: | ||
""" | ||
Metadata used in the NeXus format, | ||
see https://manual.nexusformat.org/classes/base_classes/NXcrystal.html | ||
""" | ||
|
||
usage: Literal["Bragg", "Laue"] | ||
type: str | ||
reflection: tuple[int, int, int] | ||
d_spacing: tuple[float, str] | ||
|
||
@staticmethod | ||
def calculate_default_d_spacing( | ||
lattice_parameter: float, reflection: tuple[int, int, int] | ||
) -> tuple[float, str]: | ||
""" | ||
Calculates the d-spacing value in nanometers based on the given lattice parameter and reflection indices. | ||
""" | ||
h_index, k_index, l_index = reflection | ||
d_spacing_m = lattice_parameter / math.sqrt( | ||
h_index**2 + k_index**2 + l_index**2 | ||
) | ||
d_spacing_nm = d_spacing_m * 1e9 # Convert meters to nanometers | ||
return round(d_spacing_nm, 5), "nm" | ||
|
||
|
||
def make_crystal_metadata_from_material( | ||
material: MaterialsEnum, | ||
reflection_plane: tuple[int, int, int], | ||
usage: Literal["Bragg", "Laue"] = "Bragg", | ||
d_spacing_param: tuple[float, str] | None = None, | ||
): | ||
d_spacing = d_spacing_param or CrystalMetadata.calculate_default_d_spacing( | ||
material.value.lattice_parameter, reflection_plane | ||
) | ||
assert all( | ||
isinstance(i, int) and i > 0 for i in reflection_plane | ||
), "Reflection plane indices must be positive integers" | ||
return CrystalMetadata(usage, material.value.name, reflection_plane, d_spacing) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import pytest | ||
|
||
from dodal.common.crystal_metadata import ( | ||
MaterialsEnum, | ||
make_crystal_metadata_from_material, | ||
) | ||
|
||
|
||
def test_happy_path_silicon(): | ||
crystal_metadata = make_crystal_metadata_from_material(MaterialsEnum.Si, (3, 1, 1)) | ||
|
||
# Check the values | ||
assert crystal_metadata.type == "silicon" | ||
assert crystal_metadata.reflection == (3, 1, 1) | ||
assert crystal_metadata.d_spacing == pytest.approx( | ||
(0.16375, "nm"), rel=1e-3 | ||
) # Allow for small tolerance | ||
assert crystal_metadata.usage == "Bragg" | ||
|
||
|
||
def test_happy_path_germanium(): | ||
crystal_metadata = make_crystal_metadata_from_material(MaterialsEnum.Ge, (1, 1, 1)) | ||
# Check the values | ||
assert crystal_metadata.type == "germanium" | ||
assert crystal_metadata.reflection == (1, 1, 1) | ||
assert crystal_metadata.d_spacing == pytest.approx( | ||
(0.326633, "nm"), rel=1e-3 | ||
) # Allow for small tolerance | ||
assert crystal_metadata.usage == "Bragg" | ||
|
||
|
||
def test_invalid_reflection_plane_with_negative_number(): | ||
with pytest.raises( | ||
AssertionError, | ||
match="Reflection plane indices must be positive integers", | ||
): | ||
make_crystal_metadata_from_material(MaterialsEnum.Si, (-1, 2, 3)) |
Oops, something went wrong.