diff --git a/src/diffcalc_API/errors/HklCalculation.py b/src/diffcalc_API/errors/HklCalculation.py index 5dd33f4..bc3d37c 100644 --- a/src/diffcalc_API/errors/HklCalculation.py +++ b/src/diffcalc_API/errors/HklCalculation.py @@ -1,6 +1,7 @@ -from typing import Tuple +from typing import Optional, Tuple, Union import numpy as np +from diffcalc.hkl.calc import HklCalculation from diffcalc_API.errorDefinitions import DiffcalcAPIException, ErrorCodes, allResponses @@ -8,6 +9,7 @@ class codes(ErrorCodes): check_valid_miller_indices = 400 check_valid_scan_bounds = 400 + calculate_UB_matrix = 400 responses = {code: allResponses[code] for code in np.unique(codes().all_codes())} @@ -32,3 +34,18 @@ def check_valid_scan_bounds(start: float, stop: float, inc: float): ), ) return + + +def calculate_UB_matrix( + hkl: HklCalculation, + firstTag: Optional[Union[int, str]], + secondTag: Optional[Union[int, str]], +) -> None: + try: + hkl.ubcalc.calc_ub(firstTag, secondTag) + except Exception as e: + raise DiffcalcAPIException( + status_code=codes.calculate_UB_matrix, + detail=f"Error calculating UB matrix: {str(e)}", + ) + return diff --git a/src/diffcalc_API/errors/UBCalculation.py b/src/diffcalc_API/errors/UBCalculation.py index c23ec99..2ec5860 100644 --- a/src/diffcalc_API/errors/UBCalculation.py +++ b/src/diffcalc_API/errors/UBCalculation.py @@ -1,4 +1,4 @@ -from typing import Optional, Union +from typing import Union import numpy as np from diffcalc.hkl.calc import HklCalculation @@ -14,7 +14,6 @@ class codes(ErrorCodes): get_reflection = 403 get_orientation = 403 check_property_is_valid = 400 - calculate_UB_matrix = 400 responses = {code: allResponses[code] for code in np.unique(codes().all_codes())} @@ -68,18 +67,3 @@ def check_property_is_valid(property: str) -> None: detail=f"invalid property. Choose one of: {VectorProperties}", ) return - - -def calculate_UB_matrix( - hkl: HklCalculation, - firstTag: Optional[Union[int, str]], - secondTag: Optional[Union[int, str]], -) -> None: - try: - hkl.ubcalc.calc_ub(firstTag, secondTag) - except Exception as e: - raise DiffcalcAPIException( - status_code=codes.calculate_UB_matrix, - detail=f"Error calculating UB matrix: {e.__str__()}", - ) - return diff --git a/src/diffcalc_API/routes/Constraints.py b/src/diffcalc_API/routes/Constraints.py index e2edf62..b29c0fb 100644 --- a/src/diffcalc_API/routes/Constraints.py +++ b/src/diffcalc_API/routes/Constraints.py @@ -3,7 +3,7 @@ from diffcalc.hkl.calc import HklCalculation from diffcalc.hkl.constraints import Constraints -from fastapi import APIRouter, Body, Depends +from fastapi import APIRouter, Body, Depends, Response from diffcalc_API.config import constraintsWithNoValue from diffcalc_API.errors.Constraints import check_constraint_exists @@ -15,6 +15,13 @@ singleConstraintType = Union[Tuple[str, float], str] +@router.get("/{name}") +async def get_constraints_status( + name: str, hklCalc: HklCalculation = Depends(unpickleHkl) +): + return Response(content=str(hklCalc.constraints), media_type="application/text") + + @router.put("/{name}/set") async def set_constraints( name: str, @@ -33,7 +40,6 @@ async def set_constraints( return {"message": f"constraints updated (replaced) for crystal {name}"} -# is patch the correct choice here? What about delete instead? @router.patch("/{name}/unconstrain/{property}") async def remove_constraint( name: str, diff --git a/src/diffcalc_API/routes/HklCalculation.py b/src/diffcalc_API/routes/HklCalculation.py index c8aeb50..e201010 100644 --- a/src/diffcalc_API/routes/HklCalculation.py +++ b/src/diffcalc_API/routes/HklCalculation.py @@ -1,16 +1,18 @@ from itertools import product -from typing import Dict, List, Tuple, Union +from pathlib import Path +from typing import Callable, Dict, List, Optional, Tuple, Union import numpy as np from diffcalc.hkl.calc import HklCalculation from diffcalc.hkl.geometry import Position -from fastapi import APIRouter, Depends, Query +from fastapi import APIRouter, Depends, Query, Response from diffcalc_API.errors.HklCalculation import ( + calculate_UB_matrix, check_valid_miller_indices, check_valid_scan_bounds, ) -from diffcalc_API.fileHandling import unpickleHkl +from diffcalc_API.fileHandling import supplyPersist, unpickleHkl router = APIRouter(prefix="/calculate", tags=["hkl"]) @@ -19,6 +21,22 @@ positionType = Tuple[float, float, float] +@router.get("/{name}/UB") +async def calculate_UB( + name: str, + firstTag: Optional[Union[int, str]] = Query(default=None, example="refl1"), + secondTag: Optional[Union[int, str]] = Query(default=None, example="plane"), + hklCalc: HklCalculation = Depends(unpickleHkl), + persist: Callable[[HklCalculation, str], Path] = Depends(supplyPersist), +): + calculate_UB_matrix(hklCalc, firstTag, secondTag) + + persist(hklCalc, name) + return Response( + content=str(np.round(hklCalc.ubcalc.UB, 6)), media_type="application/text" + ) + + @router.get("/{name}/position/lab") async def lab_position_from_miller_indices( name: str, diff --git a/src/diffcalc_API/routes/UBCalculation.py b/src/diffcalc_API/routes/UBCalculation.py index 513ddb5..753a6c9 100644 --- a/src/diffcalc_API/routes/UBCalculation.py +++ b/src/diffcalc_API/routes/UBCalculation.py @@ -1,14 +1,11 @@ -import json from pathlib import Path -from typing import Callable, Optional, Tuple, Union +from typing import Callable, Tuple, Union -import numpy as np from diffcalc.hkl.calc import HklCalculation from diffcalc.hkl.geometry import Position -from fastapi import APIRouter, Body, Depends, Query +from fastapi import APIRouter, Body, Depends, Response from diffcalc_API.errors.UBCalculation import ( - calculate_UB_matrix, check_params_not_empty, check_property_is_valid, get_orientation, @@ -27,6 +24,11 @@ router = APIRouter(prefix="/ub", tags=["ub"]) +@router.get("/{name}") +async def get_UB_status(name: str, hklCalc: HklCalculation = Depends(unpickleHkl)): + return Response(content=str(hklCalc.ubcalc), media_type="application/text") + + @router.put("/{name}/reflection") async def add_reflection( name: str, @@ -172,20 +174,6 @@ async def modify_property( return {"message": f"{property} set for UB calculation of crystal {name}"} -@router.get("/{name}/UB") -async def calculate_UB( - name: str, - firstTag: Optional[Union[int, str]] = Query(default=None, example="refl1"), - secondTag: Optional[Union[int, str]] = Query(default=None, example="plane"), - hklCalc: HklCalculation = Depends(unpickleHkl), - persist: Callable[[HklCalculation, str], Path] = Depends(supplyPersist), -): - calculate_UB_matrix(hklCalc, firstTag, secondTag) - - persist(hklCalc, name) - return json.dumps(np.round(hklCalc.ubcalc.UB, 6).tolist()) - - @router.delete("/{name}/reflection") async def delete_reflection( name: str, diff --git a/src/diffcalc_API/server.py b/src/diffcalc_API/server.py index 683cfb2..8669c80 100644 --- a/src/diffcalc_API/server.py +++ b/src/diffcalc_API/server.py @@ -24,7 +24,7 @@ async def diffcalc_exception_handler(request: Request, exc: DiffcalcException): return responses.JSONResponse( status_code=400, - content={"message": exc.__str__(), "type": str(type(exc))}, + content={"message": str(exc), "type": str(type(exc))}, ) @@ -46,7 +46,7 @@ async def server_exceptions_middleware(request: Request, call_next): return responses.JSONResponse( status_code=500, - content={"message": e.__str__(), "type": str(type(e))}, + content={"message": str(e), "type": str(type(e))}, ) diff --git a/tests/test_hklcalc.py b/tests/test_hklcalc.py index 13fee59..7448174 100644 --- a/tests/test_hklcalc.py +++ b/tests/test_hklcalc.py @@ -142,3 +142,24 @@ def test_invalid_scans(client: TestClient): ) assert invalidWavelengthScan.status_code == codes.check_valid_scan_bounds + + +def test_calculate_UB(client: TestClient): + response = client.get( + "/calculate/test/UB", params={"firstTag": "refl1", "secondTag": "plane"} + ) + expected_UB = ( + "[[ 1.27889 -0. 0. ], [-0. 1.278111 0.04057 ]," + " [-0. -0.044633 1.161768]]" + ) + + assert response.status_code == 200 + assert response.text.replace("\n", ", ") == expected_UB + + +def test_calculate_UB_fails_when_incorrect_tags(client: TestClient): + response = client.get( + "/calculate/test/UB", params={"firstTag": "one", "secondTag": "two"} + ) + + assert response.status_code == codes.calculate_UB_matrix diff --git a/tests/test_ubcalc.py b/tests/test_ubcalc.py index 41c1993..aff4b7d 100644 --- a/tests/test_ubcalc.py +++ b/tests/test_ubcalc.py @@ -1,4 +1,3 @@ -import ast from pathlib import Path import numpy as np @@ -202,22 +201,3 @@ def test_modify_non_existent_property(client: TestClient): json=[0, 0, 1], ) assert response.status_code == codes.check_property_is_valid - - -def test_calculate_UB(client: TestClient): - dummyHkl.ubcalc.add_reflection([0, 0, 1], Position(7, 0, 10, 0, 0, 0), 12, "foo") - dummyHkl.ubcalc.add_orientation([0, 1, 0], [0, 1, 0], None, "bar") - dummyHkl.ubcalc.set_lattice(name="test", a=2) - - response = client.get("/ub/test/UB", params={"firstTag": "foo", "secondTag": "bar"}) - - expected_UB = [[3.141593, 0, 0], [0, 3.139679, 0.10964], [-0, -0.10964, 3.139679]] - - assert response.status_code == 200 - assert ast.literal_eval(response._content.decode().replace('"', "")) == expected_UB - - -def test_calculate_UB_fails_when_incorrect_tags(client: TestClient): - response = client.get("/ub/test/UB", params={"firstTag": "one", "secondTag": "two"}) - - assert response.status_code == codes.calculate_UB_matrix