diff --git a/src/diffcalc_api/models/ub.py b/src/diffcalc_api/models/ub.py index 6109611..95c6b05 100644 --- a/src/diffcalc_api/models/ub.py +++ b/src/diffcalc_api/models/ub.py @@ -53,6 +53,14 @@ class AddReflectionParams(BaseModel): energy: float +class RefineUbParams(BaseModel): + """Request body definition to refine the UB matrix.""" + + hkl: HklModel + position: PositionModel + wavelength: float + + class AddOrientationParams(BaseModel): """Request body definition to add an orientation of the UB calculation.""" diff --git a/src/diffcalc_api/routes/ub.py b/src/diffcalc_api/routes/ub.py index 07e69d3..5fd8e92 100644 --- a/src/diffcalc_api/routes/ub.py +++ b/src/diffcalc_api/routes/ub.py @@ -30,6 +30,7 @@ HklModel, MiscutModel, PositionModel, + RefineUbParams, SetLatticeParams, SphericalCoordinates, XyzModel, @@ -597,6 +598,35 @@ async def get_u( return ArrayResponse(payload=content) +@router.patch("/{name}/refine", response_model=InfoResponse) +async def refine_ub( + name: str, + params: RefineUbParams = Body(...), + refine_lattice: bool = Query(default=False), + refine_u_matrix: bool = Query(default=False), + store: HklCalcStore = Depends(get_store), + collection: Optional[str] = Query(default=None, example="B07"), +): + """Refine the UB matrix to match the diffractometer position to a given reflection. + + Args: + name: the name of the hkl object to access within the store + params: the parameters to use to refine the UB matrix + store: accessor to the hkl object + collection: collection within which the hkl object resides + + """ + await service.refine_ub( + name, params, refine_lattice, refine_u_matrix, store, collection + ) + return InfoResponse( + message=( + f"lattice has been set for UB calculation of crystal {name} in " + + f"collection {collection}" + ) + ) + + ####################################################################################### # Surface and Reference Vectors # ####################################################################################### diff --git a/src/diffcalc_api/services/ub.py b/src/diffcalc_api/services/ub.py index fdfd593..400c521 100644 --- a/src/diffcalc_api/services/ub.py +++ b/src/diffcalc_api/services/ub.py @@ -20,6 +20,7 @@ EditReflectionParams, HklModel, PositionModel, + RefineUbParams, SetLatticeParams, XyzModel, ) @@ -614,6 +615,38 @@ async def set_ub( await store.save(name, hklcalc, collection) +async def refine_ub( + name: str, + params: RefineUbParams, + refine_lat: bool, + refine_u: bool, + store: HklCalcStore, + collection: Optional[str], +) -> None: + """Refine the UB matrix to match the reflection given in the parameters. + + Args: + name: the name of the hkl object to access within the store + params: parameters for refining the UB matrix. + store: accessor to the hkl object + collection: collection within which the hkl object resides + """ + hklcalc = await store.load(name, collection) + + ubcalc: UBCalculation = hklcalc.ubcalc + hkl: Tuple[float, float, float] = params.hkl.h, params.hkl.k, params.hkl.l + + ubcalc.refine_ub( + hkl, + Position(**params.position.dict()), + params.wavelength, + refine_lattice=refine_lat, + refine_umatrix=refine_u, + ) + + await store.save(name, hklcalc, collection) + + ####################################################################################### # Surface and Reference Vectors # ####################################################################################### diff --git a/tests/test_ubcalc.py b/tests/test_ubcalc.py index 897e699..f3b858f 100644 --- a/tests/test_ubcalc.py +++ b/tests/test_ubcalc.py @@ -1,5 +1,6 @@ import ast from ast import literal_eval +from math import radians from typing import Dict import numpy as np @@ -516,6 +517,43 @@ def test_set_ub(): ) +def test_refine_ub(): + ubcalc = UBCalculation() + hkl = HklCalculation(ubcalc, Constraints()) + client = Client(hkl).client + + ubcalc.set_lattice("LSMO_327", 3.78, 3.78, 20.1, 90, 90, 90) + ubcalc.add_orientation([0, 0, 1], [1, 0, 0]) + ubcalc.add_orientation([0, 1, 0], [0, 1, 0]) + + ubcalc.calc_ub() + + ubcalc.n_phi = [0.0, 1.0, 0.0] + + ubcalc.set_miscut([1.0, 0.0, 0.0], radians(3)) + + ub_after_miscut = ubcalc.UB + + client.patch( + "/ub/test/refine?collection=B07", + json={ + "hkl": {"h": 0, "k": 0, "l": 2}, + "position": { + "mu": 100.0, + "delta": 0.0, + "nu": 82.9408, + "eta": 0.0, + "chi": 30.31, + "phi": 0.0, + }, + "wavelength": 13.3109, + }, + params={"refine_lattice": 1, "refine_u_matrix": 1}, + ) + + assert np.any(ubcalc.UB != ub_after_miscut) + + @pytest.mark.parametrize( ["url", "body", "property"], [