diff --git a/Pipfile.lock b/Pipfile.lock index 59ee943..f3f6ea1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -44,11 +44,11 @@ }, "fastapi": { "hashes": [ - "sha256:15fcabd5c78c266fa7ae7d8de9b384bfc2375ee0503463a6febbe3bab69d6f65", - "sha256:3233d4a789ba018578658e2af1a4bb5e38bdd122ff722b313666a9b2c6786a83" + "sha256:cf0ff6db25b91d321050c4112baab0908c90f19b40bf257f9591d2f9780d1f22", + "sha256:d337563424ceada23857f73d5abe8dae0c28e4cccb53b2af06e78b7bb4a1c7d7" ], "markers": "python_full_version >= '3.6.1'", - "version": "==0.78.0" + "version": "==0.79.0" }, "h11": { "hashes": [ @@ -295,50 +295,50 @@ "toml" ], "hashes": [ - "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749", - "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982", - "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3", - "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9", - "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428", - "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e", - "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c", - "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9", - "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264", - "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605", - "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397", - "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d", - "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c", - "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815", - "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068", - "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b", - "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4", - "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4", - "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3", - "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84", - "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83", - "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4", - "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8", - "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb", - "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d", - "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df", - "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6", - "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b", - "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72", - "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13", - "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df", - "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc", - "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6", - "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28", - "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b", - "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4", - "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad", - "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46", - "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3", - "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9", - "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54" + "sha256:0895ea6e6f7f9939166cc835df8fa4599e2d9b759b02d1521b574e13b859ac32", + "sha256:0f211df2cba951ffcae210ee00e54921ab42e2b64e0bf2c0befc977377fb09b7", + "sha256:147605e1702d996279bb3cc3b164f408698850011210d133a2cb96a73a2f7996", + "sha256:24b04d305ea172ccb21bee5bacd559383cba2c6fcdef85b7701cf2de4188aa55", + "sha256:25b7ec944f114f70803d6529394b64f8749e93cbfac0fe6c5ea1b7e6c14e8a46", + "sha256:2b20286c2b726f94e766e86a3fddb7b7e37af5d0c635bdfa7e4399bc523563de", + "sha256:2dff52b3e7f76ada36f82124703f4953186d9029d00d6287f17c68a75e2e6039", + "sha256:2f8553878a24b00d5ab04b7a92a2af50409247ca5c4b7a2bf4eabe94ed20d3ee", + "sha256:3def6791adf580d66f025223078dc84c64696a26f174131059ce8e91452584e1", + "sha256:422fa44070b42fef9fb8dabd5af03861708cdd6deb69463adc2130b7bf81332f", + "sha256:4f89d8e03c8a3757aae65570d14033e8edf192ee9298303db15955cadcff0c63", + "sha256:5336e0352c0b12c7e72727d50ff02557005f79a0b8dcad9219c7c4940a930083", + "sha256:54d8d0e073a7f238f0666d3c7c0d37469b2aa43311e4024c925ee14f5d5a1cbe", + "sha256:5ef42e1db047ca42827a85e34abe973971c635f83aed49611b7f3ab49d0130f0", + "sha256:5f65e5d3ff2d895dab76b1faca4586b970a99b5d4b24e9aafffc0ce94a6022d6", + "sha256:6c3ccfe89c36f3e5b9837b9ee507472310164f352c9fe332120b764c9d60adbe", + "sha256:6d0b48aff8e9720bdec315d67723f0babd936a7211dc5df453ddf76f89c59933", + "sha256:6fe75dcfcb889b6800f072f2af5a331342d63d0c1b3d2bf0f7b4f6c353e8c9c0", + "sha256:79419370d6a637cb18553ecb25228893966bd7935a9120fa454e7076f13b627c", + "sha256:7bb00521ab4f99fdce2d5c05a91bddc0280f0afaee0e0a00425e28e209d4af07", + "sha256:80db4a47a199c4563d4a25919ff29c97c87569130375beca3483b41ad5f698e8", + "sha256:866ebf42b4c5dbafd64455b0a1cd5aa7b4837a894809413b930026c91e18090b", + "sha256:8af6c26ba8df6338e57bedbf916d76bdae6308e57fc8f14397f03b5da8622b4e", + "sha256:a13772c19619118903d65a91f1d5fea84be494d12fd406d06c849b00d31bf120", + "sha256:a697977157adc052284a7160569b36a8bbec09db3c3220642e6323b47cec090f", + "sha256:a9032f9b7d38bdf882ac9f66ebde3afb8145f0d4c24b2e600bc4c6304aafb87e", + "sha256:b5e28db9199dd3833cc8a07fa6cf429a01227b5d429facb56eccd765050c26cd", + "sha256:c77943ef768276b61c96a3eb854eba55633c7a3fddf0a79f82805f232326d33f", + "sha256:d230d333b0be8042ac34808ad722eabba30036232e7a6fb3e317c49f61c93386", + "sha256:d4548be38a1c810d79e097a38107b6bf2ff42151900e47d49635be69943763d8", + "sha256:d4e7ced84a11c10160c0697a6cc0b214a5d7ab21dfec1cd46e89fbf77cc66fae", + "sha256:d56f105592188ce7a797b2bd94b4a8cb2e36d5d9b0d8a1d2060ff2a71e6b9bbc", + "sha256:d714af0bdba67739598849c9f18efdcc5a0412f4993914a0ec5ce0f1e864d783", + "sha256:d774d9e97007b018a651eadc1b3970ed20237395527e22cbeb743d8e73e0563d", + "sha256:e0524adb49c716ca763dbc1d27bedce36b14f33e6b8af6dba56886476b42957c", + "sha256:e2618cb2cf5a7cc8d698306e42ebcacd02fb7ef8cfc18485c59394152c70be97", + "sha256:e36750fbbc422c1c46c9d13b937ab437138b998fe74a635ec88989afb57a3978", + "sha256:edfdabe7aa4f97ed2b9dd5dde52d2bb29cb466993bb9d612ddd10d0085a683cf", + "sha256:f22325010d8824594820d6ce84fa830838f581a7fd86a9235f0d2ed6deb61e29", + "sha256:f23876b018dfa5d3e98e96f5644b109090f16a4acb22064e0f06933663005d39", + "sha256:f7bd0ffbcd03dc39490a1f40b2669cc414fae0c4e16b77bb26806a4d0b7d1452" ], "markers": "python_version >= '3.7'", - "version": "==6.4.1" + "version": "==6.4.2" }, "diffcalc-api": { "editable": true, @@ -354,10 +354,10 @@ }, "distlib": { "hashes": [ - "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b", - "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579" + "sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe", + "sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c" ], - "version": "==0.3.4" + "version": "==0.3.5" }, "docutils": { "hashes": [ @@ -369,11 +369,11 @@ }, "fastapi": { "hashes": [ - "sha256:15fcabd5c78c266fa7ae7d8de9b384bfc2375ee0503463a6febbe3bab69d6f65", - "sha256:3233d4a789ba018578658e2af1a4bb5e38bdd122ff722b313666a9b2c6786a83" + "sha256:cf0ff6db25b91d321050c4112baab0908c90f19b40bf257f9591d2f9780d1f22", + "sha256:d337563424ceada23857f73d5abe8dae0c28e4cccb53b2af06e78b7bb4a1c7d7" ], "markers": "python_full_version >= '3.6.1'", - "version": "==0.78.0" + "version": "==0.79.0" }, "filelock": { "hashes": [ @@ -609,6 +609,13 @@ ], "version": "==0.9.0" }, + "pep8-naming": { + "hashes": [ + "sha256:3af77cdaa9c7965f7c85a56cd579354553c9bbd3fdf3078a776f12db54dd6944", + "sha256:f7867c1a464fe769be4f972ef7b79d6df1d9aff1b1f04ecf738d471963d3ab9c" + ], + "version": "==0.13.1" + }, "pip": { "hashes": [ "sha256:6d55b27e10f506312894a87ccc59f280136bad9061719fac9101bdad5a6bce69", @@ -831,11 +838,11 @@ }, "setuptools": { "hashes": [ - "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", - "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" + "sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16", + "sha256:c04b44a57a6265fe34a4a444e965884716d34bae963119a76353434d6f18e450" ], "markers": "python_version >= '3.7'", - "version": "==63.1.0" + "version": "==63.2.0" }, "six": { "hashes": [ @@ -1035,11 +1042,11 @@ }, "zipp": { "hashes": [ - "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad", - "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099" + "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", + "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" ], "markers": "python_version >= '3.7'", - "version": "==3.8.0" + "version": "==3.8.1" } } } diff --git a/setup.cfg b/setup.cfg index fbfbf78..edfde36 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,6 +43,7 @@ dev = pre-commit pipenv typed-ast + pep8-naming mock [options.packages.find] diff --git a/src/diffcalc_API/__init__.py b/src/diffcalc_API/__init__.py index 5b67131..9d42edd 100644 --- a/src/diffcalc_API/__init__.py +++ b/src/diffcalc_API/__init__.py @@ -1,4 +1,4 @@ -from . import config, errorDefinitions, server +from . import config, server from ._version_git import __version__ # __all__ defines the public API for the package. @@ -6,6 +6,5 @@ __all__ = [ "__version__", "server", - "errorDefinitions", "config", ] diff --git a/src/diffcalc_API/config.py b/src/diffcalc_API/config.py index 999a628..72353df 100644 --- a/src/diffcalc_API/config.py +++ b/src/diffcalc_API/config.py @@ -1,11 +1,10 @@ # this file is for defining constants -savePicklesFolder = "/dls/tmp/ton99817/diffcalc_pickles" -VectorProperties = ["n_hkl", "n_phi", "surf_nhkl", "surf_nphi"] -pickledNames = {"ub", "constraints", "hkl"} -constraintsWithNoValue = {"a_eq_b", "bin_eq_bout", "mu_is_gam", "bisect"} +SAVE_PICKLES_FOLDER = "/dls/tmp/ton99817/diffcalc_pickles" +VECTOR_PROPERTIES = ["n_hkl", "n_phi", "surf_nhkl", "surf_nphi"] +CONSTRAINTS_WITH_NO_VALUE = {"a_eq_b", "bin_eq_bout", "mu_is_gam", "bisect"} -allConstraints = { +ALL_CONSTRAINTS = { "delta", "gam" "qaz", "naz", diff --git a/src/diffcalc_API/errors/Constraints.py b/src/diffcalc_API/errors/Constraints.py deleted file mode 100644 index 94dd4d1..0000000 --- a/src/diffcalc_API/errors/Constraints.py +++ /dev/null @@ -1,22 +0,0 @@ -import numpy as np - -from diffcalc_API.config import allConstraints -from diffcalc_API.errorDefinitions import DiffcalcAPIException, ErrorCodes, allResponses - - -class codes(ErrorCodes): - check_constraint_exists = 400 - - -responses = {code: allResponses[code] for code in np.unique(codes().all_codes())} - - -def check_constraint_exists(constraint: str) -> None: - if constraint not in allConstraints: - raise DiffcalcAPIException( - status_code=codes.check_constraint_exists, - detail=( - f"property {constraint} does not exist as a valid constraint." - f" Choose one of {allConstraints}" - ), - ) diff --git a/src/diffcalc_API/errors/UBCalculation.py b/src/diffcalc_API/errors/UBCalculation.py deleted file mode 100644 index 2ec5860..0000000 --- a/src/diffcalc_API/errors/UBCalculation.py +++ /dev/null @@ -1,69 +0,0 @@ -from typing import Union - -import numpy as np -from diffcalc.hkl.calc import HklCalculation -from diffcalc.ub.reference import Orientation, Reflection - -from diffcalc_API.config import VectorProperties -from diffcalc_API.errorDefinitions import DiffcalcAPIException, ErrorCodes, allResponses -from diffcalc_API.models.UBCalculation import setLatticeParams - - -class codes(ErrorCodes): - check_params_not_empty = 400 - get_reflection = 403 - get_orientation = 403 - check_property_is_valid = 400 - - -responses = {code: allResponses[code] for code in np.unique(codes().all_codes())} - - -def check_params_not_empty(params: setLatticeParams) -> None: - nonEmptyVariables = [var for var, value in params if value is not None] - - if len(nonEmptyVariables) == 0: - raise DiffcalcAPIException( - status_code=codes.check_params_not_empty, - detail="please provide parameters in request body", - ) - return - - -def get_reflection(hkl: HklCalculation, tagOrIdx: Union[str, int]) -> Reflection: - try: - reflection = hkl.ubcalc.get_reflection(tagOrIdx) - except Exception: - raise DiffcalcAPIException( - status_code=codes.get_reflection, - detail=( - "Cannot edit or delete reflection: " - "No reflection with this tag or index" - ), - ) - - return reflection - - -def get_orientation(hkl: HklCalculation, tagOrIdx: Union[str, int]) -> Orientation: - try: - orientation = hkl.ubcalc.get_orientation(tagOrIdx) - except Exception: - raise DiffcalcAPIException( - status_code=codes.get_orientation, - detail=( - "Cannot edit or delete orientation: " - "No orientation with this tag or index" - ), - ) - - return orientation - - -def check_property_is_valid(property: str) -> None: - if property not in VectorProperties: - raise DiffcalcAPIException( - status_code=codes.check_property_is_valid, - detail=f"invalid property. Choose one of: {VectorProperties}", - ) - return diff --git a/src/diffcalc_API/errors/__init__.py b/src/diffcalc_API/errors/__init__.py index 8eced8a..92906ae 100644 --- a/src/diffcalc_API/errors/__init__.py +++ b/src/diffcalc_API/errors/__init__.py @@ -1,3 +1,3 @@ -from diffcalc_API.errors import Constraints, HklCalculation, UBCalculation +from diffcalc_API.errors import constraints, hkl, ub -__all__ = ["HklCalculation", "UBCalculation", "Constraints"] +__all__ = ["hkl", "ub", "constraints"] diff --git a/src/diffcalc_API/errors/constraints.py b/src/diffcalc_API/errors/constraints.py new file mode 100644 index 0000000..37b646b --- /dev/null +++ b/src/diffcalc_API/errors/constraints.py @@ -0,0 +1,26 @@ +import numpy as np + +from diffcalc_API.config import ALL_CONSTRAINTS +from diffcalc_API.errors.definitions import ( + ALL_RESPONSES, + DiffcalcAPIException, + ErrorCodes, +) + + +class Codes(ErrorCodes): + CHECK_CONSTRAINT_EXISTS = 400 + + +responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())} + + +def check_constraint_exists(constraint: str) -> None: + if constraint not in ALL_CONSTRAINTS: + raise DiffcalcAPIException( + status_code=Codes.CHECK_CONSTRAINT_EXISTS, + detail=( + f"property {constraint} does not exist as a valid constraint." + f" Choose one of {ALL_CONSTRAINTS}" + ), + ) diff --git a/src/diffcalc_API/errorDefinitions.py b/src/diffcalc_API/errors/definitions.py similarity index 58% rename from src/diffcalc_API/errorDefinitions.py rename to src/diffcalc_API/errors/definitions.py index 1a31acb..8e88a8e 100644 --- a/src/diffcalc_API/errorDefinitions.py +++ b/src/diffcalc_API/errors/definitions.py @@ -1,11 +1,8 @@ -from pathlib import Path +from typing import Any, Dict, Union -import numpy as np from diffcalc.util import DiffcalcException from pydantic import BaseModel -from diffcalc_API.config import savePicklesFolder - ####################################################################################### # Class definitions # ####################################################################################### @@ -39,45 +36,14 @@ def all_codes(self): ####################################################################################### -# Error throwing functions # +# All possible error responses # ####################################################################################### -class codes(ErrorCodes): - attempting_to_overwrite = 405 - check_file_exists = 404 - - -allResponses = { +ALL_RESPONSES: Dict[Union[int, str], Dict[str, Any]] = { 400: {"model": DiffcalcExceptionModel, "description": "Bad Request"}, 403: {"model": DiffcalcExceptionModel, "description": "Forbidden Request"}, 404: {"model": DiffcalcExceptionModel, "description": "Resource Not Found"}, 405: {"model": DiffcalcExceptionModel, "description": "Request disabled"}, 500: {"model": DiffcalcExceptionModel, "description": "Internal Server Error"}, } - -responses = {code: allResponses[code] for code in np.unique(codes().all_codes())} - - -def attempting_to_overwrite(fileName: str) -> None: - pickledFile = Path(savePicklesFolder) / fileName - if (pickledFile).is_file(): - errorMessage = ( - f"File already exists for crystal {fileName}!" - f"\nEither delete via DELETE request to this URL " - f"or change the existing properties. " - ) - raise DiffcalcAPIException(status_code=405, detail=errorMessage) - - return - - -def check_file_exists(pickledFile: Path, name: str) -> None: - if not (pickledFile).is_file(): - errorMessage = ( - f"File for crystal {name} not found." - f"\nYou need to post to" - f" http://localhost:8000/{name}" - f" first to generate the pickled file.\n" - ) - raise DiffcalcAPIException(status_code=404, detail=errorMessage) diff --git a/src/diffcalc_API/errors/HklCalculation.py b/src/diffcalc_API/errors/hkl.py similarity index 50% rename from src/diffcalc_API/errors/HklCalculation.py rename to src/diffcalc_API/errors/hkl.py index bc3d37c..5cb7ac2 100644 --- a/src/diffcalc_API/errors/HklCalculation.py +++ b/src/diffcalc_API/errors/hkl.py @@ -3,22 +3,26 @@ import numpy as np from diffcalc.hkl.calc import HklCalculation -from diffcalc_API.errorDefinitions import DiffcalcAPIException, ErrorCodes, allResponses +from diffcalc_API.errors.definitions import ( + ALL_RESPONSES, + DiffcalcAPIException, + ErrorCodes, +) -class codes(ErrorCodes): - check_valid_miller_indices = 400 - check_valid_scan_bounds = 400 - calculate_UB_matrix = 400 +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())} +responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())} -def check_valid_miller_indices(millerIndices: Tuple[float, float, float]) -> None: - if sum(millerIndices) == 0: +def check_valid_miller_indices(miller_indices: Tuple[float, float, float]) -> None: + if sum(miller_indices) == 0: raise DiffcalcAPIException( - status_code=codes.check_valid_miller_indices, + status_code=Codes.CHECK_VALID_MILLER_INDICES, detail="At least one of the hkl indices must be non-zero", ) return @@ -27,7 +31,7 @@ def check_valid_miller_indices(millerIndices: Tuple[float, float, float]) -> Non def check_valid_scan_bounds(start: float, stop: float, inc: float): if len(np.arange(start, stop + inc, inc)) == 0: raise DiffcalcAPIException( - status_code=codes.check_valid_scan_bounds, + status_code=Codes.CHECK_VALID_SCAN_BOUNDS, detail=( f"numpy range cannot be formed from start: {start}" f" to stop: {stop} in increments of: {inc}" @@ -36,16 +40,16 @@ def check_valid_scan_bounds(start: float, stop: float, inc: float): return -def calculate_UB_matrix( +def calculate_ub_matrix( hkl: HklCalculation, - firstTag: Optional[Union[int, str]], - secondTag: Optional[Union[int, str]], + first_tag: Optional[Union[int, str]], + second_tag: Optional[Union[int, str]], ) -> None: try: - hkl.ubcalc.calc_ub(firstTag, secondTag) + hkl.ubcalc.calc_ub(first_tag, second_tag) except Exception as e: raise DiffcalcAPIException( - status_code=codes.calculate_UB_matrix, + status_code=Codes.CALCULATE_UB_MATRIX, detail=f"Error calculating UB matrix: {str(e)}", ) return diff --git a/src/diffcalc_API/errors/ub.py b/src/diffcalc_API/errors/ub.py new file mode 100644 index 0000000..d9b9ec5 --- /dev/null +++ b/src/diffcalc_API/errors/ub.py @@ -0,0 +1,71 @@ +from typing import Union + +import numpy as np +from diffcalc.hkl.calc import HklCalculation +from diffcalc.ub.reference import Orientation, Reflection + +from diffcalc_API.config import VECTOR_PROPERTIES +from diffcalc_API.errors.definitions import ( + ALL_RESPONSES, + DiffcalcAPIException, + ErrorCodes, +) +from diffcalc_API.models.ub import SetLatticeParams + + +class Codes(ErrorCodes): + CHECK_PARAMS_NOT_EMPTY = 400 + GET_REFLECTION = 403 + GET_ORIENTATION = 403 + CHECK_PROPERTY_IS_VALID = 400 + + +responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())} + + +def check_params_not_empty(params: SetLatticeParams) -> None: + non_empty_vars = [var for var, value in params if value is not None] + + if len(non_empty_vars) == 0: + raise DiffcalcAPIException( + status_code=Codes.CHECK_PARAMS_NOT_EMPTY, + detail="please provide parameters in request body", + ) + + +def get_reflection(hkl: HklCalculation, tag_or_idx: Union[str, int]) -> Reflection: + try: + reflection = hkl.ubcalc.get_reflection(tag_or_idx) + except Exception: + raise DiffcalcAPIException( + status_code=Codes.GET_REFLECTION, + detail=( + "Cannot edit or delete reflection: " + "No reflection with this tag or index" + ), + ) + + return reflection + + +def get_orientation(hkl: HklCalculation, tag_or_idx: Union[str, int]) -> Orientation: + try: + orientation = hkl.ubcalc.get_orientation(tag_or_idx) + except Exception: + raise DiffcalcAPIException( + status_code=Codes.GET_ORIENTATION, + detail=( + "Cannot edit or delete orientation: " + "No orientation with this tag or index" + ), + ) + + return orientation + + +def check_property_is_valid(property: str) -> None: + if property not in VECTOR_PROPERTIES: + raise DiffcalcAPIException( + status_code=Codes.CHECK_PROPERTY_IS_VALID, + detail=f"invalid property. Choose one of: {VECTOR_PROPERTIES}", + ) diff --git a/src/diffcalc_API/examples/UBCalculation.py b/src/diffcalc_API/examples/UBCalculation.py deleted file mode 100644 index 1835138..0000000 --- a/src/diffcalc_API/examples/UBCalculation.py +++ /dev/null @@ -1,37 +0,0 @@ -from diffcalc_API.models.UBCalculation import ( - addOrientationParams, - addReflectionParams, - editOrientationParams, - editReflectionParams, - setLatticeParams, -) - -addReflection: addReflectionParams = addReflectionParams( - **{ - "hkl": [0, 0, 1], - "position": [7.31, 0.0, 10.62, 0, 0.0, 0], - "energy": 12.39842, - "tag": "refl1", - } -) - -editReflection: editReflectionParams = editReflectionParams( - **{"energy": 12.45, "tagOrIdx": "refl1"} -) - -addOrientation: addOrientationParams = addOrientationParams( - **{ - "hkl": [0, 1, 0], - "xyz": [0, 1, 0], - "tag": "plane", - } -) - -editOrientation: editOrientationParams = editOrientationParams( - **{ - "hkl": (0, 1, 0), - "tagOrIdx": "plane", - } -) - -setLattice: setLatticeParams = setLatticeParams(**{"a": 4.913, "c": 5.405}) diff --git a/src/diffcalc_API/examples/__init__.py b/src/diffcalc_API/examples/__init__.py index f18cbe3..603a2eb 100644 --- a/src/diffcalc_API/examples/__init__.py +++ b/src/diffcalc_API/examples/__init__.py @@ -1,3 +1,3 @@ -from diffcalc_API.examples import UBCalculation +from diffcalc_API.examples import ub -__all__ = ["UBCalculation"] +__all__ = ["ub"] diff --git a/src/diffcalc_API/examples/ub.py b/src/diffcalc_API/examples/ub.py new file mode 100644 index 0000000..6e22730 --- /dev/null +++ b/src/diffcalc_API/examples/ub.py @@ -0,0 +1,37 @@ +from diffcalc_API.models.ub import ( + AddOrientationParams, + AddReflectionParams, + EditOrientationParams, + EditReflectionParams, + SetLatticeParams, +) + +add_reflection: AddReflectionParams = AddReflectionParams( + **{ + "hkl": [0, 0, 1], + "position": [7.31, 0.0, 10.62, 0, 0.0, 0], + "energy": 12.39842, + "tag": "refl1", + } +) + +edit_reflection: EditReflectionParams = EditReflectionParams( + **{"energy": 12.45, "tag_or_idx": "refl1"} +) + +add_orientation: AddOrientationParams = AddOrientationParams( + **{ + "hkl": [0, 1, 0], + "xyz": [0, 1, 0], + "tag": "plane", + } +) + +edit_orientation: EditOrientationParams = EditOrientationParams( + **{ + "hkl": (0, 1, 0), + "tag_or_idx": "plane", + } +) + +set_lattice: SetLatticeParams = SetLatticeParams(**{"a": 4.913, "c": 5.405}) diff --git a/src/diffcalc_API/models/__init__.py b/src/diffcalc_API/models/__init__.py index 5d83401..09bc5bc 100644 --- a/src/diffcalc_API/models/__init__.py +++ b/src/diffcalc_API/models/__init__.py @@ -1,3 +1,3 @@ -from diffcalc_API.models import UBCalculation +from diffcalc_API.models import ub -__all__ = ["UBCalculation"] +__all__ = ["ub"] diff --git a/src/diffcalc_API/models/UBCalculation.py b/src/diffcalc_API/models/ub.py similarity index 76% rename from src/diffcalc_API/models/UBCalculation.py rename to src/diffcalc_API/models/ub.py index 5d83a86..cb79b95 100644 --- a/src/diffcalc_API/models/UBCalculation.py +++ b/src/diffcalc_API/models/ub.py @@ -3,7 +3,7 @@ from pydantic import BaseModel -class setLatticeParams(BaseModel): +class SetLatticeParams(BaseModel): system: Optional[Union[str, float]] = None a: Optional[float] = None b: Optional[float] = None @@ -13,7 +13,7 @@ class setLatticeParams(BaseModel): gamma: Optional[float] = None -class addReflectionParams(BaseModel): +class AddReflectionParams(BaseModel): hkl: Tuple[float, float, float] position: Tuple[ float, float, float, float, float, float @@ -22,26 +22,26 @@ class addReflectionParams(BaseModel): tag: Optional[str] = None -class addOrientationParams(BaseModel): +class AddOrientationParams(BaseModel): hkl: Tuple[float, float, float] xyz: Tuple[float, float, float] position: Optional[Tuple[float, float, float, float, float, float]] = None tag: Optional[str] = None -class editReflectionParams(BaseModel): +class EditReflectionParams(BaseModel): hkl: Optional[Tuple[float, float, float]] = None position: Optional[Tuple[float, float, float, float, float, float]] = None energy: Optional[float] = None - tagOrIdx: Union[int, str] + tag_or_idx: Union[int, str] -class editOrientationParams(BaseModel): +class EditOrientationParams(BaseModel): hkl: Optional[Tuple[float, float, float]] = None xyz: Optional[Tuple[float, float, float]] = None position: Optional[Tuple[float, float, float, float, float, float]] = None - tagOrIdx: Union[int, str] + tag_or_idx: Union[int, str] -class deleteParams(BaseModel): - tagOrIdx: Union[int, str] +class DeleteParams(BaseModel): + tag_or_idx: Union[int, str] diff --git a/src/diffcalc_API/routes/__init__.py b/src/diffcalc_API/routes/__init__.py index ebc0f5a..9f64f11 100644 --- a/src/diffcalc_API/routes/__init__.py +++ b/src/diffcalc_API/routes/__init__.py @@ -1,3 +1,3 @@ -from diffcalc_API.routes import Constraints, HklCalculation, UBCalculation +from diffcalc_API.routes import constraints, hkl, ub -__all__ = ["UBCalculation", "HklCalculation", "Constraints"] +__all__ = ["ub", "hkl", "constraints"] diff --git a/src/diffcalc_API/routes/Constraints.py b/src/diffcalc_API/routes/constraints.py similarity index 88% rename from src/diffcalc_API/routes/Constraints.py rename to src/diffcalc_API/routes/constraints.py index c15593a..f79d5ed 100644 --- a/src/diffcalc_API/routes/Constraints.py +++ b/src/diffcalc_API/routes/constraints.py @@ -2,7 +2,7 @@ from fastapi import APIRouter, Body, Depends, Response -from diffcalc_API.services import Constraints as service +from diffcalc_API.services import constraints as service from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore @@ -19,12 +19,12 @@ async def get_constraints(name: str, store: HklCalcStore = Depends(get_store)): @router.put("/{name}/set") async def set_constraints( name: str, - constraintDict: Dict[str, Union[float, bool]] = Body( + constraints: Dict[str, Union[float, bool]] = Body( example={"qaz": 0, "alpha": 0, "eta": 0} ), store: HklCalcStore = Depends(get_store), ): - await service.set_constraints(name, constraintDict, store) + await service.set_constraints(name, constraints, store) return {"message": f"constraints updated (replaced) for crystal {name}"} diff --git a/src/diffcalc_API/routes/HklCalculation.py b/src/diffcalc_API/routes/hkl.py similarity index 63% rename from src/diffcalc_API/routes/HklCalculation.py rename to src/diffcalc_API/routes/hkl.py index b22d0ce..e1257e1 100644 --- a/src/diffcalc_API/routes/HklCalculation.py +++ b/src/diffcalc_API/routes/hkl.py @@ -2,37 +2,37 @@ from fastapi import APIRouter, Depends, Query, Response -from diffcalc_API.services import HklCalculation as service +from diffcalc_API.services import hkl as service from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore router = APIRouter(prefix="/calculate", tags=["hkl"]) -singleConstraintType = Union[Tuple[str, float], str] -positionType = Tuple[float, float, float] +SingleConstraint = Union[Tuple[str, float], str] +PositionType = Tuple[float, float, float] @router.get("/{name}/UB") -async def calculate_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"), + first_tag: Optional[Union[int, str]] = Query(default=None, example="refl1"), + second_tag: Optional[Union[int, str]] = Query(default=None, example="plane"), store: HklCalcStore = Depends(get_store), ): - content = await service.calculate_UB(name, firstTag, secondTag, store) + content = await service.calculate_ub(name, first_tag, second_tag, store) return Response(content=content, media_type="application/text") @router.get("/{name}/position/lab") async def lab_position_from_miller_indices( name: str, - millerIndices: Tuple[float, float, float] = Query(example=[0, 0, 1]), + miller_indices: Tuple[float, float, float] = Query(example=[0, 0, 1]), wavelength: float = Query(..., example=1.0), store: HklCalcStore = Depends(get_store), ): positions = await service.lab_position_from_miller_indices( - name, millerIndices, wavelength, store + name, miller_indices, wavelength, store ) return {"payload": positions} @@ -54,14 +54,14 @@ async def miller_indices_from_lab_position( @router.get("/{name}/scan/hkl") async def scan_hkl( name: str, - start: positionType = Query(..., example=(1, 0, 1)), - stop: positionType = Query(..., example=(2, 0, 2)), - inc: positionType = Query(..., example=(0.1, 0, 0.1)), + start: PositionType = Query(..., example=(1, 0, 1)), + stop: PositionType = Query(..., example=(2, 0, 2)), + inc: PositionType = Query(..., example=(0.1, 0, 0.1)), wavelength: float = Query(..., example=1), store: HklCalcStore = Depends(get_store), ): - scanResults = await service.scan_hkl(name, start, stop, inc, wavelength, store) - return {"payload": scanResults} + scan_results = await service.scan_hkl(name, start, stop, inc, wavelength, store) + return {"payload": scan_results} @router.get("/{name}/scan/wavelength") @@ -70,11 +70,11 @@ async def scan_wavelength( start: float = Query(..., example=1.0), stop: float = Query(..., example=2.0), inc: float = Query(..., example=0.2), - hkl: positionType = Query(..., example=(1, 0, 1)), + hkl: PositionType = Query(..., example=(1, 0, 1)), store: HklCalcStore = Depends(get_store), ): - scanResults = await service.scan_wavelength(name, start, stop, inc, hkl, store) - return {"payload": scanResults} + scan_results = await service.scan_wavelength(name, start, stop, inc, hkl, store) + return {"payload": scan_results} @router.get("/{name}/scan/{constraint}") @@ -84,12 +84,12 @@ async def scan_constraint( start: float = Query(..., example=1), stop: float = Query(..., example=4), inc: float = Query(..., example=1), - hkl: positionType = Query(..., example=(1, 0, 1)), + hkl: PositionType = Query(..., example=(1, 0, 1)), wavelength: float = Query(..., example=1.0), store: HklCalcStore = Depends(get_store), ): - scanResults = await service.scan_constraint( + scan_results = await service.scan_constraint( name, constraint, start, stop, inc, hkl, wavelength, store ) - return {"payload": scanResults} + return {"payload": scan_results} diff --git a/src/diffcalc_API/routes/UBCalculation.py b/src/diffcalc_API/routes/ub.py similarity index 57% rename from src/diffcalc_API/routes/UBCalculation.py rename to src/diffcalc_API/routes/ub.py index 0193dea..08e271d 100644 --- a/src/diffcalc_API/routes/UBCalculation.py +++ b/src/diffcalc_API/routes/ub.py @@ -2,20 +2,17 @@ from fastapi import APIRouter, Body, Depends, Response -from diffcalc_API.errors.UBCalculation import ( - check_params_not_empty, - check_property_is_valid, +from diffcalc_API.errors.ub import check_params_not_empty, check_property_is_valid +from diffcalc_API.examples import ub as examples +from diffcalc_API.models.ub import ( + AddOrientationParams, + AddReflectionParams, + DeleteParams, + EditOrientationParams, + EditReflectionParams, + SetLatticeParams, ) -from diffcalc_API.examples import UBCalculation as examples -from diffcalc_API.models.UBCalculation import ( - addOrientationParams, - addReflectionParams, - deleteParams, - editOrientationParams, - editReflectionParams, - setLatticeParams, -) -from diffcalc_API.services import UBCalculation as service +from diffcalc_API.services import ub as service from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore @@ -23,15 +20,15 @@ @router.get("/{name}") -async def get_UB(name: str, store: HklCalcStore = Depends(get_store)): - content = await service.get_UB(name, store) +async def get_ub(name: str, store: HklCalcStore = Depends(get_store)): + content = await service.get_ub(name, store) return Response(content=content, media_type="application/text") @router.put("/{name}/reflection") async def add_reflection( name: str, - params: addReflectionParams = Body(..., example=examples.addReflection), + params: AddReflectionParams = Body(..., example=examples.add_reflection), store: HklCalcStore = Depends(get_store), ): await service.add_reflection(name, params, store) @@ -41,27 +38,27 @@ async def add_reflection( @router.patch("/{name}/reflection") async def edit_reflection( name: str, - params: editReflectionParams = Body(..., example=examples.editReflection), + params: EditReflectionParams = Body(..., example=examples.edit_reflection), store: HklCalcStore = Depends(get_store), ): await service.edit_reflection(name, params, store) - return {"message": f"reflection with tag/index {params.tagOrIdx} edited. "} + return {"message": f"reflection with tag/index {params.tag_or_idx} edited. "} @router.delete("/{name}/reflection") async def delete_reflection( name: str, - params: deleteParams = Body(..., example={"tagOrIdx": "refl1"}), + params: DeleteParams = Body(..., example={"tag_or_idx": "refl1"}), store: HklCalcStore = Depends(get_store), ): - await service.delete_reflection(name, params.tagOrIdx, store) # TODO Change this! - return {"message": f"reflection with tag/index {params.tagOrIdx} deleted."} + await service.delete_reflection(name, params.tag_or_idx, store) # TODO Change this! + return {"message": f"reflection with tag/index {params.tag_or_idx} deleted."} @router.put("/{name}/orientation") async def add_orientation( name: str, - params: addOrientationParams = Body(..., example=examples.addOrientation), + params: AddOrientationParams = Body(..., example=examples.add_orientation), store: HklCalcStore = Depends(get_store), ): await service.add_orientation(name, params, store) @@ -71,27 +68,27 @@ async def add_orientation( @router.patch("/{name}/orientation") async def edit_orientation( name: str, - params: editOrientationParams = Body(..., example=examples.editOrientation), + params: EditOrientationParams = Body(..., example=examples.edit_orientation), store: HklCalcStore = Depends(get_store), ): await service.edit_orientation(name, params, store) - return {"message": f"orientation with tag/index {params.tagOrIdx} edited."} + return {"message": f"orientation with tag/index {params.tag_or_idx} edited."} @router.delete("/{name}/orientation") async def delete_orientation( name: str, - params: deleteParams = Body(..., example={"tagOrIdx": "plane"}), + params: DeleteParams = Body(..., example={"tag_or_idx": "plane"}), store: HklCalcStore = Depends(get_store), ): - await service.delete_orientation(name, params.tagOrIdx, store) - return {"message": f"reflection with tag or index {params.tagOrIdx} deleted."} + await service.delete_orientation(name, params.tag_or_idx, store) + return {"message": f"reflection with tag or index {params.tag_or_idx} deleted."} @router.patch("/{name}/lattice") async def set_lattice( name: str, - params: setLatticeParams = Body(example=examples.setLattice), + params: SetLatticeParams = Body(example=examples.set_lattice), store: HklCalcStore = Depends(get_store), _=Depends(check_params_not_empty), ): @@ -103,9 +100,9 @@ async def set_lattice( async def modify_property( name: str, property: str, - targetValue: Tuple[float, float, float] = Body(..., example=[1, 0, 0]), + target_value: Tuple[float, float, float] = Body(..., example=[1, 0, 0]), store: HklCalcStore = Depends(get_store), _=Depends(check_property_is_valid), ): - await service.modify_property(name, property, targetValue, store) + await service.modify_property(name, property, target_value, store) return {"message": f"{property} has been set for UB calculation of crystal {name}"} diff --git a/src/diffcalc_API/server.py b/src/diffcalc_API/server.py index 16c9636..7b132ef 100644 --- a/src/diffcalc_API/server.py +++ b/src/diffcalc_API/server.py @@ -1,19 +1,19 @@ from diffcalc.util import DiffcalcException from fastapi import Depends, FastAPI, Request, responses -from diffcalc_API import errorDefinitions -from diffcalc_API.errors.Constraints import responses as responsesConstraints -from diffcalc_API.errors.HklCalculation import responses as responsesHkl -from diffcalc_API.errors.UBCalculation import responses as responsesUb +from diffcalc_API.errors.constraints import responses as constraints_responses +from diffcalc_API.errors.definitions import DiffcalcAPIException +from diffcalc_API.errors.hkl import responses as hkl_responses +from diffcalc_API.errors.ub import responses as ub_responses from diffcalc_API.stores.pickling import get_store from . import routes -app = FastAPI(responses=errorDefinitions.responses) +app = FastAPI(responses=get_store().responses) -app.include_router(routes.UBCalculation.router, responses=responsesUb) -app.include_router(routes.Constraints.router, responses=responsesConstraints) -app.include_router(routes.HklCalculation.router, responses=responsesHkl) +app.include_router(routes.ub.router, responses=ub_responses) +app.include_router(routes.constraints.router, responses=constraints_responses) +app.include_router(routes.hkl.router, responses=hkl_responses) ####################################################################################### # Middleware for Exceptions # @@ -28,10 +28,8 @@ async def diffcalc_exception_handler(request: Request, exc: DiffcalcException): ) -@app.exception_handler(errorDefinitions.DiffcalcAPIException) -async def http_exception_handler( - request: Request, exc: errorDefinitions.DiffcalcAPIException -): +@app.exception_handler(DiffcalcAPIException) +async def http_exception_handler(request: Request, exc: DiffcalcAPIException): return responses.JSONResponse( status_code=exc.status_code, content={"message": exc.detail, "type": str(type(exc))}, diff --git a/src/diffcalc_API/services/Constraints.py b/src/diffcalc_API/services/Constraints.py deleted file mode 100644 index 1a6e8ce..0000000 --- a/src/diffcalc_API/services/Constraints.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import Dict, Union - -from diffcalc.hkl.constraints import Constraints - -from diffcalc_API.config import constraintsWithNoValue -from diffcalc_API.errors.Constraints import check_constraint_exists -from diffcalc_API.stores.protocol import HklCalcStore - - -async def get_constraints(name: str, store: HklCalcStore) -> str: - hklCalc = await store.load(name) - return str(hklCalc.constraints) - - -async def set_constraints( - name: str, - constraintDict: Dict[str, Union[float, bool]], - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - booleanConstraints = set(constraintDict.keys()).intersection(constraintsWithNoValue) - for constraint in booleanConstraints: - constraintDict[constraint] = bool(constraintDict[constraint]) - - hklCalc.constraints = Constraints(constraintDict) - - await store.save(name, hklCalc) - - -async def remove_constraint( - name: str, - property: str, - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - check_constraint_exists(property) - setattr(hklCalc.constraints, property, None) - - await store.save(name, hklCalc) - - -async def set_constraint( - name: str, - property: str, - value: Union[float, bool], - store: HklCalcStore, -): - hklCalc = await store.load(name) - - check_constraint_exists(property) - if property in constraintsWithNoValue: - value = bool(value) - - setattr(hklCalc.constraints, property, value) - - await store.save(name, hklCalc) diff --git a/src/diffcalc_API/services/UBCalculation.py b/src/diffcalc_API/services/UBCalculation.py deleted file mode 100644 index 691200e..0000000 --- a/src/diffcalc_API/services/UBCalculation.py +++ /dev/null @@ -1,139 +0,0 @@ -from typing import Tuple, Union - -from diffcalc.hkl.geometry import Position - -from diffcalc_API.errors.UBCalculation import get_orientation, get_reflection -from diffcalc_API.models.UBCalculation import ( - addOrientationParams, - addReflectionParams, - editOrientationParams, - editReflectionParams, - setLatticeParams, -) -from diffcalc_API.stores.protocol import HklCalcStore - - -async def get_UB(name: str, store: HklCalcStore) -> str: - hklCalc = await store.load(name) - - return str(hklCalc.ubcalc) - - -async def add_reflection( - name: str, - params: addReflectionParams, - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - hklCalc.ubcalc.add_reflection( - params.hkl, - Position(*params.position), - params.energy, - params.tag, - ) - - await store.save(name, hklCalc) - - -async def edit_reflection( - name: str, - params: editReflectionParams, - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - reflection = get_reflection(hklCalc, params.tagOrIdx) - hklCalc.ubcalc.edit_reflection( - params.tagOrIdx, - params.hkl if params.hkl else (reflection.h, reflection.k, reflection.l), - Position(params.position) if params.position else reflection.pos, - params.energy if params.energy else reflection.energy, - params.tagOrIdx if isinstance(params.tagOrIdx, str) else None, - ) - - await store.save(name, hklCalc) - - -async def delete_reflection( - name: str, - tagOrIdx: Union[str, int], - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - _ = get_reflection(hklCalc, tagOrIdx) - hklCalc.ubcalc.del_reflection(tagOrIdx) - - await store.save(name, hklCalc) - - -async def add_orientation( - name: str, - params: addOrientationParams, - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - position = Position(*params.position) if params.position else None - hklCalc.ubcalc.add_orientation( - params.hkl, - params.xyz, - position, - params.tag, - ) - - await store.save(name, hklCalc) - - -async def edit_orientation( - name: str, - params: editOrientationParams, - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - orientation = get_orientation(hklCalc, params.tagOrIdx) - hklCalc.ubcalc.edit_orientation( - params.tagOrIdx, - params.hkl if params.hkl else (orientation.h, orientation.k, orientation.l), - params.xyz if params.xyz else (orientation.x, orientation.y, orientation.z), - Position(params.position) if params.position else orientation.pos, - params.tagOrIdx if isinstance(params.tagOrIdx, str) else None, - ) - - await store.save(name, hklCalc) - - -async def delete_orientation( - name: str, - tagOrIdx: Union[str, int], - store: HklCalcStore, -) -> None: - hklCalc = await store.load(name) - - _ = get_orientation(hklCalc, tagOrIdx) - hklCalc.ubcalc.del_orientation(tagOrIdx) - - await store.save(name, hklCalc) - - -async def set_lattice(name: str, params: setLatticeParams, store: HklCalcStore) -> None: - hklCalc = await store.load(name) - - hklCalc.ubcalc.set_lattice(name=name, **params.dict()) - - await store.save(name, hklCalc) - - -async def modify_property( - name: str, - property: str, - targetValue: Tuple[float, float, float], - store: HklCalcStore, -): - hklCalc = await store.load(name) - - setattr(hklCalc.ubcalc, property, targetValue) - - await store.save(name, hklCalc) diff --git a/src/diffcalc_API/services/__init__.py b/src/diffcalc_API/services/__init__.py index 132d9e5..2350aac 100644 --- a/src/diffcalc_API/services/__init__.py +++ b/src/diffcalc_API/services/__init__.py @@ -1,3 +1,3 @@ -from diffcalc_API.services import Constraints, HklCalculation, UBCalculation +from diffcalc_API.services import constraints, hkl, ub -__all__ = ["UBCalculation", "HklCalculation", "Constraints"] +__all__ = ["ub", "hkl", "constraints"] diff --git a/src/diffcalc_API/services/constraints.py b/src/diffcalc_API/services/constraints.py new file mode 100644 index 0000000..fea4f77 --- /dev/null +++ b/src/diffcalc_API/services/constraints.py @@ -0,0 +1,60 @@ +from typing import Dict, Union + +from diffcalc.hkl.constraints import Constraints + +from diffcalc_API.config import CONSTRAINTS_WITH_NO_VALUE +from diffcalc_API.errors.constraints import check_constraint_exists +from diffcalc_API.stores.protocol import HklCalcStore + + +async def get_constraints(name: str, store: HklCalcStore) -> str: + hklcalc = await store.load(name) + return str(hklcalc.constraints) + + +async def set_constraints( + name: str, + constraints: Dict[str, Union[float, bool]], + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + boolean_constraints = set(constraints.keys()).intersection( + CONSTRAINTS_WITH_NO_VALUE + ) + for constraint in boolean_constraints: + constraints[constraint] = bool(constraints[constraint]) + + hklcalc.constraints = Constraints(constraints) + + await store.save(name, hklcalc) + + +async def remove_constraint( + name: str, + property: str, + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + check_constraint_exists(property) + setattr(hklcalc.constraints, property, None) + + await store.save(name, hklcalc) + + +async def set_constraint( + name: str, + property: str, + value: Union[float, bool], + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + check_constraint_exists(property) + if property in CONSTRAINTS_WITH_NO_VALUE: + value = bool(value) + + setattr(hklcalc.constraints, property, value) + + await store.save(name, hklcalc) diff --git a/src/diffcalc_API/services/HklCalculation.py b/src/diffcalc_API/services/hkl.py similarity index 55% rename from src/diffcalc_API/services/HklCalculation.py rename to src/diffcalc_API/services/hkl.py index 48f2df3..894fb83 100644 --- a/src/diffcalc_API/services/HklCalculation.py +++ b/src/diffcalc_API/services/hkl.py @@ -1,11 +1,11 @@ from itertools import product -from typing import Dict, List, Optional, Tuple, Union +from typing import Any, Dict, List, Optional, Tuple, Union import numpy as np from diffcalc.hkl.geometry import Position -from diffcalc_API.errors.HklCalculation import ( - calculate_UB_matrix, +from diffcalc_API.errors.hkl import ( + calculate_ub_matrix, check_valid_miller_indices, check_valid_scan_bounds, ) @@ -16,16 +16,16 @@ async def lab_position_from_miller_indices( name: str, - millerIndices: Tuple[float, float, float], + miller_indices: Tuple[float, float, float], wavelength: float, store: HklCalcStore, -) -> List[Tuple[Position, Dict[str, float]]]: - hklCalc = await store.load(name) +) -> List[Dict[str, float]]: + hklcalc = await store.load(name) - check_valid_miller_indices(millerIndices) - allPositions = hklCalc.get_position(*millerIndices, wavelength) + check_valid_miller_indices(miller_indices) + all_positions = hklcalc.get_position(*miller_indices, wavelength) - return combine_lab_position_results(allPositions) + return combine_lab_position_results(all_positions) async def miller_indices_from_lab_position( @@ -33,10 +33,10 @@ async def miller_indices_from_lab_position( pos: Tuple[float, float, float, float, float, float], wavelength: float, store: HklCalcStore, -): - hklCalc = await store.load(name) - hklPosition = hklCalc.get_hkl(Position(*pos), wavelength) - return tuple(np.round(hklPosition, 16)) +) -> Tuple[Any, ...]: + hklcalc = await store.load(name) + position = hklcalc.get_hkl(Position(*pos), wavelength) + return tuple(np.round(position, 16)) async def scan_hkl( @@ -46,19 +46,19 @@ async def scan_hkl( inc: PositionType, wavelength: float, store: HklCalcStore, -): - hklCalc = await store.load(name) - valueOfAxes = [ +) -> Dict[str, List[Dict[str, float]]]: + hklcalc = await store.load(name) + axes_values = [ generate_axis(start[i], stop[i], inc[i]) if inc[i] != 0 else [0] for i in range(3) ] results = {} - for h, k, l in product(*valueOfAxes): + for h, k, l in product(*axes_values): check_valid_miller_indices((h, k, l)) - allPositions = hklCalc.get_position(h, k, l, wavelength) - results[f"({h}, {k}, {l})"] = combine_lab_position_results(allPositions) + all_positions = hklcalc.get_position(h, k, l, wavelength) + results[f"({h}, {k}, {l})"] = combine_lab_position_results(all_positions) return results @@ -70,15 +70,15 @@ async def scan_wavelength( inc: float, hkl: PositionType, store: HklCalcStore, -): - hklCalc = await store.load(name) +) -> Dict[str, List[Dict[str, float]]]: + hklcalc = await store.load(name) check_valid_scan_bounds(start, stop, inc) wavelengths = np.arange(start, stop + inc, inc) result = {} for wavelength in wavelengths: - allPositions = hklCalc.get_position(*hkl, wavelength) - result[f"{wavelength}"] = combine_lab_position_results(allPositions) + all_positions = hklcalc.get_position(*hkl, wavelength) + result[f"{wavelength}"] = combine_lab_position_results(all_positions) return result @@ -92,14 +92,14 @@ async def scan_constraint( hkl: PositionType, wavelength: float, store: HklCalcStore, -): - hklCalc = await store.load(name) +) -> Dict[str, List[Dict[str, float]]]: + hklcalc = await store.load(name) check_valid_scan_bounds(start, stop, inc) result = {} for value in np.arange(start, stop + inc, inc): - setattr(hklCalc, constraint, value) - allPositions = hklCalc.get_position(*hkl, wavelength) - result[f"{value}"] = combine_lab_position_results(allPositions) + setattr(hklcalc, constraint, value) + all_positions = hklcalc.get_position(*hkl, wavelength) + result[f"{value}"] = combine_lab_position_results(all_positions) return result @@ -109,7 +109,9 @@ def generate_axis(start: float, stop: float, inc: float): return np.arange(start, stop + inc, inc) -def combine_lab_position_results(positions: List[Tuple[Position, Dict[str, float]]]): +def combine_lab_position_results( + positions: List[Tuple[Position, Dict[str, float]]] +) -> List[Dict[str, float]]: result = [] for position in positions: @@ -118,15 +120,15 @@ def combine_lab_position_results(positions: List[Tuple[Position, Dict[str, float return result -async def calculate_UB( +async def calculate_ub( name: str, - firstTag: Optional[Union[int, str]], - secondTag: Optional[Union[int, str]], + first_tag: Optional[Union[int, str]], + second_tag: Optional[Union[int, str]], store: HklCalcStore, ) -> str: - hklCalc = await store.load(name) + hklcalc = await store.load(name) - calculate_UB_matrix(hklCalc, firstTag, secondTag) + calculate_ub_matrix(hklcalc, first_tag, second_tag) - await store.save(name, hklCalc) - return str(np.round(hklCalc.ubcalc.UB, 6)) + await store.save(name, hklcalc) + return str(np.round(hklcalc.ubcalc.UB, 6)) diff --git a/src/diffcalc_API/services/ub.py b/src/diffcalc_API/services/ub.py new file mode 100644 index 0000000..1f9ffed --- /dev/null +++ b/src/diffcalc_API/services/ub.py @@ -0,0 +1,139 @@ +from typing import Tuple, Union + +from diffcalc.hkl.geometry import Position + +from diffcalc_API.errors.ub import get_orientation, get_reflection +from diffcalc_API.models.ub import ( + AddOrientationParams, + AddReflectionParams, + EditOrientationParams, + EditReflectionParams, + SetLatticeParams, +) +from diffcalc_API.stores.protocol import HklCalcStore + + +async def get_ub(name: str, store: HklCalcStore) -> str: + hklcalc = await store.load(name) + + return str(hklcalc.ubcalc) + + +async def add_reflection( + name: str, + params: AddReflectionParams, + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + hklcalc.ubcalc.add_reflection( + params.hkl, + Position(*params.position), + params.energy, + params.tag, + ) + + await store.save(name, hklcalc) + + +async def edit_reflection( + name: str, + params: EditReflectionParams, + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + reflection = get_reflection(hklcalc, params.tag_or_idx) + hklcalc.ubcalc.edit_reflection( + params.tag_or_idx, + params.hkl if params.hkl else (reflection.h, reflection.k, reflection.l), + Position(params.position) if params.position else reflection.pos, + params.energy if params.energy else reflection.energy, + params.tag_or_idx if isinstance(params.tag_or_idx, str) else None, + ) + + await store.save(name, hklcalc) + + +async def delete_reflection( + name: str, + tag_or_idx: Union[str, int], + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + _ = get_reflection(hklcalc, tag_or_idx) + hklcalc.ubcalc.del_reflection(tag_or_idx) + + await store.save(name, hklcalc) + + +async def add_orientation( + name: str, + params: AddOrientationParams, + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + position = Position(*params.position) if params.position else None + hklcalc.ubcalc.add_orientation( + params.hkl, + params.xyz, + position, + params.tag, + ) + + await store.save(name, hklcalc) + + +async def edit_orientation( + name: str, + params: EditOrientationParams, + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + orientation = get_orientation(hklcalc, params.tag_or_idx) + hklcalc.ubcalc.edit_orientation( + params.tag_or_idx, + params.hkl if params.hkl else (orientation.h, orientation.k, orientation.l), + params.xyz if params.xyz else (orientation.x, orientation.y, orientation.z), + Position(params.position) if params.position else orientation.pos, + params.tag_or_idx if isinstance(params.tag_or_idx, str) else None, + ) + + await store.save(name, hklcalc) + + +async def delete_orientation( + name: str, + tag_or_idx: Union[str, int], + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + _ = get_orientation(hklcalc, tag_or_idx) + hklcalc.ubcalc.del_orientation(tag_or_idx) + + await store.save(name, hklcalc) + + +async def set_lattice(name: str, params: SetLatticeParams, store: HklCalcStore) -> None: + hklcalc = await store.load(name) + + hklcalc.ubcalc.set_lattice(name=name, **params.dict()) + + await store.save(name, hklcalc) + + +async def modify_property( + name: str, + property: str, + target_value: Tuple[float, float, float], + store: HklCalcStore, +) -> None: + hklcalc = await store.load(name) + + setattr(hklcalc.ubcalc, property, target_value) + + await store.save(name, hklcalc) diff --git a/src/diffcalc_API/stores/pickling.py b/src/diffcalc_API/stores/pickling.py index 307ead6..de2b289 100644 --- a/src/diffcalc_API/stores/pickling.py +++ b/src/diffcalc_API/stores/pickling.py @@ -1,34 +1,71 @@ import pickle from pathlib import Path +import numpy as np from diffcalc.hkl.calc import HklCalculation from diffcalc.hkl.constraints import Constraints from diffcalc.ub.calc import UBCalculation -from diffcalc_API.config import savePicklesFolder -from diffcalc_API.errorDefinitions import attempting_to_overwrite, check_file_exists +from diffcalc_API.config import SAVE_PICKLES_FOLDER +from diffcalc_API.errors.definitions import ( + ALL_RESPONSES, + DiffcalcAPIException, + ErrorCodes, +) from diffcalc_API.stores.protocol import HklCalcStore +class Codes(ErrorCodes): + attempting_to_overwrite = 405 + check_file_exists = 404 + + +def attempting_to_overwrite(filename: str) -> None: + pickled_file = Path(SAVE_PICKLES_FOLDER) / filename + if (pickled_file).is_file(): + message = ( + f"File already exists for crystal {filename}!" + f"\nEither delete via DELETE request to this URL " + f"or change the existing properties. " + ) + raise DiffcalcAPIException(status_code=405, detail=message) + + return + + +def check_file_exists(pickled_file: Path, name: str) -> None: + if not (pickled_file).is_file(): + message = ( + f"File for crystal {name} not found." + f"\nYou need to post to" + f" http://localhost:8000/{name}" + f" first to generate the pickled file.\n" + ) + raise DiffcalcAPIException(status_code=404, detail=message) + + class PicklingHklCalcStore: _root_directory: Path def __init__(self, root_directory: Path) -> None: self._root_directory = root_directory + self.responses = { + code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes()) + } async def create(self, name: str) -> None: attempting_to_overwrite(name) - UBcalc = UBCalculation(name=name) + ubcalc = UBCalculation(name=name) constraints = Constraints() - hkl = HklCalculation(UBcalc, constraints) + hkl = HklCalculation(ubcalc, constraints) await self.save(name, hkl) async def delete(self, name: str) -> None: - pickleFilePath = Path(savePicklesFolder) / name - check_file_exists(pickleFilePath, name) - Path(pickleFilePath).unlink() + pickle_file_path = Path(SAVE_PICKLES_FOLDER) / name + check_file_exists(pickle_file_path, name) + Path(pickle_file_path).unlink() async def save(self, name: str, calc: HklCalculation) -> None: file_path = self._root_directory / name @@ -39,11 +76,11 @@ async def load(self, name: str) -> HklCalculation: file_path = self._root_directory / name check_file_exists(file_path, name) - with open(file_path, "rb") as openedFile: - diffcalcObject: HklCalculation = pickle.load(openedFile) + with open(file_path, "rb") as stream: + hkl: HklCalculation = pickle.load(stream) - return diffcalcObject + return hkl def get_store() -> HklCalcStore: - return PicklingHklCalcStore(Path(savePicklesFolder)) + return PicklingHklCalcStore(Path(SAVE_PICKLES_FOLDER)) diff --git a/src/diffcalc_API/stores/protocol.py b/src/diffcalc_API/stores/protocol.py index 77f8c00..057d3a0 100644 --- a/src/diffcalc_API/stores/protocol.py +++ b/src/diffcalc_API/stores/protocol.py @@ -1,4 +1,4 @@ -from typing import Protocol +from typing import Any, Dict, Protocol, Union from diffcalc.hkl.calc import HklCalculation @@ -8,6 +8,8 @@ class HklCalcStore(Protocol): Protocol, or interface, for interacting with the Hkl object. """ + responses: Dict[Union[int, str], Dict[str, Any]] + async def create(self, name: str) -> None: ... diff --git a/tests/conftest.py b/tests/conftest.py index ecf354b..d7034dc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,12 @@ +from typing import Any, Dict, Union + from diffcalc.hkl.calc import HklCalculation class FakeHklCalcStore: - def __init__(self, useHkl: HklCalculation): - self.hkl = useHkl + def __init__(self, hkl: HklCalculation): + self.hkl = hkl + self.responses: Dict[Union[int, str], Dict[str, Any]] = {} async def create(self, name: str) -> None: pass diff --git a/tests/test_constraints.py b/tests/test_constraints.py index f1e87f5..af169f0 100644 --- a/tests/test_constraints.py +++ b/tests/test_constraints.py @@ -6,17 +6,17 @@ from diffcalc.ub.calc import UBCalculation from fastapi.testclient import TestClient -from diffcalc_API.errors.Constraints import codes +from diffcalc_API.errors.constraints import Codes from diffcalc_API.server import app from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore from tests.conftest import FakeHklCalcStore -dummyHkl = HklCalculation(UBCalculation(name="dummy"), Constraints()) +dummy_hkl = HklCalculation(UBCalculation(name="dummy"), Constraints()) def dummy_get_store() -> HklCalcStore: - return FakeHklCalcStore(dummyHkl) + return FakeHklCalcStore(dummy_hkl) @pytest.fixture(scope="session") @@ -37,73 +37,77 @@ def test_set_constraints(client: TestClient): ) assert response.status_code == 200 - assert dummyHkl.constraints.asdict == {"delta": 1.0, "bin_eq_bout": True, "mu": 2.0} + assert dummy_hkl.constraints.asdict == { + "delta": 1.0, + "bin_eq_bout": True, + "mu": 2.0, + } def test_set_varying_number_of_constraints_and_with_incorrect_fields( client: TestClient, ): - wrongFieldResponse = client.put( + wrong_field_response = client.put( "/constraints/test/set", json={ "fakeField": 10, }, ) - assert wrongFieldResponse.status_code == 400 # make this more concrete. + assert wrong_field_response.status_code == 400 # make this more concrete. assert ( - ast.literal_eval(wrongFieldResponse._content.decode())["type"] + ast.literal_eval(wrong_field_response._content.decode())["type"] == "" ) - tooManyFieldsResponse = client.put( + too_many_fields_response = client.put( "/constraints/test/set", json={"delta": 1, "bin_eq_bout": 1, "mu": 2, "omega": 5}, ) - assert tooManyFieldsResponse.status_code == 200 - assert dummyHkl.constraints.asdict == { + assert too_many_fields_response.status_code == 200 + assert dummy_hkl.constraints.asdict == { "delta": 1.0, "bin_eq_bout": True, "omega": 5.0, } - dummyHkl.constraints = Constraints() - tooFewFieldsResponse = client.put( + dummy_hkl.constraints = Constraints() + too_few_fields_response = client.put( "/constraints/test/set", json={"delta": 1, "bin_eq_bout": 1}, ) - assert tooFewFieldsResponse.status_code == 200 + assert too_few_fields_response.status_code == 200 def test_set_and_remove_constraint(client: TestClient): - dummyHkl.constraints = Constraints() - setResponse = client.patch( + dummy_hkl.constraints = Constraints() + set_response = client.patch( "/constraints/test/constrain/alpha", json=1, ) - assert setResponse.status_code == 200 - assert dummyHkl.constraints.asdict == {"alpha": 1.0} + assert set_response.status_code == 200 + assert dummy_hkl.constraints.asdict == {"alpha": 1.0} - removeResponse = client.patch("/constraints/test/unconstrain/alpha") + remove_response = client.patch("/constraints/test/unconstrain/alpha") - assert removeResponse.status_code == 200 - assert dummyHkl.constraints.asdict == {} + assert remove_response.status_code == 200 + assert dummy_hkl.constraints.asdict == {} def test_set_or_remove_nonexisting_constraint(client: TestClient): - dummyHkl.constraints = Constraints() - setResponse = client.patch( + dummy_hkl.constraints = Constraints() + set_response = client.patch( "/constraints/test/constrain/fake", json=1, ) - assert setResponse.status_code == codes.check_constraint_exists - assert dummyHkl.constraints.asdict == {} + assert set_response.status_code == Codes.CHECK_CONSTRAINT_EXISTS + assert dummy_hkl.constraints.asdict == {} - removeResponse = client.patch("/constraints/test/unconstrain/fake") + remove_response = client.patch("/constraints/test/unconstrain/fake") - assert removeResponse.status_code == codes.check_constraint_exists - assert dummyHkl.constraints.asdict == {} + assert remove_response.status_code == Codes.CHECK_CONSTRAINT_EXISTS + assert dummy_hkl.constraints.asdict == {} diff --git a/tests/test_hklcalc.py b/tests/test_hklcalc.py index 140214e..eff2580 100644 --- a/tests/test_hklcalc.py +++ b/tests/test_hklcalc.py @@ -6,27 +6,27 @@ from diffcalc.ub.calc import UBCalculation from fastapi.testclient import TestClient -from diffcalc_API.errors.HklCalculation import codes +from diffcalc_API.errors.hkl import Codes from diffcalc_API.server import app from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore from tests.conftest import FakeHklCalcStore -dummyHkl = HklCalculation(UBCalculation(name="sixcircle"), Constraints()) +dummy_hkl = HklCalculation(UBCalculation(name="sixcircle"), Constraints()) -dummyHkl.ubcalc.set_lattice("SiO2", 4.913, 5.405) -dummyHkl.ubcalc.n_hkl = (1, 0, 0) -dummyHkl.ubcalc.add_reflection( +dummy_hkl.ubcalc.set_lattice("SiO2", 4.913, 5.405) +dummy_hkl.ubcalc.n_hkl = (1, 0, 0) +dummy_hkl.ubcalc.add_reflection( (0, 0, 1), Position(7.31, 0, 10.62, 0, 0, 0), 12.39842, "refl1" ) -dummyHkl.ubcalc.add_orientation((0, 1, 0), (0, 1, 0), None, "plane") -dummyHkl.ubcalc.calc_ub("refl1", "plane") +dummy_hkl.ubcalc.add_orientation((0, 1, 0), (0, 1, 0), None, "plane") +dummy_hkl.ubcalc.calc_ub("refl1", "plane") -dummyHkl.constraints = Constraints({"qaz": 0, "alpha": 0, "eta": 0}) +dummy_hkl.constraints = Constraints({"qaz": 0, "alpha": 0, "eta": 0}) def dummy_get_store() -> HklCalcStore: - return FakeHklCalcStore(dummyHkl) + return FakeHklCalcStore(dummy_hkl) @pytest.fixture @@ -38,16 +38,16 @@ def client() -> TestClient: def test_miller_indices_stay_the_same_after_transformation(client: TestClient): - labPositions = client.get( + lab_positions = client.get( "/calculate/test/position/lab", - params={"millerIndices": [0, 0, 1], "wavelength": 1}, + params={"miller_indices": [0, 0, 1], "wavelength": 1}, ) - assert labPositions.status_code == 200 - possiblePositions = labPositions.json()["payload"] + assert lab_positions.status_code == 200 + possible_positions = lab_positions.json()["payload"] - for pos in possiblePositions: - millerPos = client.get( + for pos in possible_positions: + miller_positions = client.get( "/calculate/test/position/hkl", params={ "pos": [ @@ -62,14 +62,16 @@ def test_miller_indices_stay_the_same_after_transformation(client: TestClient): }, ) - assert millerPos.status_code == 200 - assert np.all(np.round(millerPos.json()["payload"], 8) == np.array([0, 0, 1])) + assert miller_positions.status_code == 200 + assert np.all( + np.round(miller_positions.json()["payload"], 8) == np.array([0, 0, 1]) + ) def test_scan_hkl( client: TestClient, ): - labPositions = client.get( + lab_positions = client.get( "/calculate/test/scan/hkl", params={ "start": [1, 0, 1], @@ -78,16 +80,16 @@ def test_scan_hkl( "wavelength": 1, }, ) - scanResults = labPositions.json()["payload"] + scan_results = lab_positions.json()["payload"] - assert labPositions.status_code == 200 - assert len(scanResults.keys()) == 9 + assert lab_positions.status_code == 200 + assert len(scan_results.keys()) == 9 def test_scan_wavelength( client: TestClient, ): - labPositions = client.get( + lab_positions = client.get( "/calculate/test/scan/wavelength", params={ "start": 1, @@ -96,16 +98,16 @@ def test_scan_wavelength( "hkl": [1, 0, 1], }, ) - scanResults = labPositions.json()["payload"] + scan_results = lab_positions.json()["payload"] - assert labPositions.status_code == 200 - assert len(scanResults.keys()) == 3 + assert lab_positions.status_code == 200 + assert len(scan_results.keys()) == 3 def test_scan_constraint( client: TestClient, ): - labPositions = client.get( + lab_positions = client.get( "/calculate/test/scan/alpha", params={ "start": 1, @@ -115,14 +117,14 @@ def test_scan_constraint( "wavelength": 1.0, }, ) - scanResults = labPositions.json()["payload"] + scan_results = lab_positions.json()["payload"] - assert labPositions.status_code == 200 - assert len(scanResults.keys()) == 3 + assert lab_positions.status_code == 200 + assert len(scan_results.keys()) == 3 def test_invalid_scans(client: TestClient): - invalidMillerIndices = client.get( + invalid_miller_indices = client.get( "/calculate/test/scan/hkl", params={ "start": [0, 0, 0], @@ -132,9 +134,9 @@ def test_invalid_scans(client: TestClient): }, ) - assert invalidMillerIndices.status_code == codes.check_valid_miller_indices + assert invalid_miller_indices.status_code == Codes.CHECK_VALID_MILLER_INDICES - invalidWavelengthScan = client.get( + invalid_wavelength_scan = client.get( "/calculate/test/scan/wavelength", params={ "start": 1, @@ -144,25 +146,25 @@ def test_invalid_scans(client: TestClient): }, ) - assert invalidWavelengthScan.status_code == codes.check_valid_scan_bounds + assert invalid_wavelength_scan.status_code == Codes.CHECK_VALID_SCAN_BOUNDS -def test_calculate_UB(client: TestClient): +def test_calc_ub(client: TestClient): response = client.get( - "/calculate/test/UB", params={"firstTag": "refl1", "secondTag": "plane"} + "/calculate/test/UB", params={"first_tag": "refl1", "second_tag": "plane"} ) - expected_UB = ( + 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 + assert response.text.replace("\n", ", ") == expected_ub -def test_calculate_UB_fails_when_incorrect_tags(client: TestClient): +def test_calc_ub_fails_when_incorrect_tags(client: TestClient): response = client.get( - "/calculate/test/UB", params={"firstTag": "one", "secondTag": "two"} + "/calculate/test/UB", params={"first_tag": "one", "second_tag": "two"} ) - assert response.status_code == codes.calculate_UB_matrix + assert response.status_code == Codes.CALCULATE_UB_MATRIX diff --git a/tests/test_ubcalc.py b/tests/test_ubcalc.py index b905f2a..d937c12 100644 --- a/tests/test_ubcalc.py +++ b/tests/test_ubcalc.py @@ -6,17 +6,17 @@ from diffcalc.ub.calc import UBCalculation from fastapi.testclient import TestClient -from diffcalc_API.errors.UBCalculation import codes +from diffcalc_API.errors.ub import Codes from diffcalc_API.server import app from diffcalc_API.stores.pickling import get_store from diffcalc_API.stores.protocol import HklCalcStore from tests.conftest import FakeHklCalcStore -dummyHkl = HklCalculation(UBCalculation(name="dummy"), Constraints()) +dummy_hkl = HklCalculation(UBCalculation(name="dummy"), Constraints()) def dummy_get_store() -> HklCalcStore: - return FakeHklCalcStore(dummyHkl) + return FakeHklCalcStore(dummy_hkl) @pytest.fixture(scope="session") @@ -38,54 +38,54 @@ def test_add_reflection(client: TestClient): ) assert response.status_code == 200 - assert dummyHkl.ubcalc.get_reflection("foo") + assert dummy_hkl.ubcalc.get_reflection("foo") - dummyHkl.ubcalc.del_reflection("foo") + dummy_hkl.ubcalc.del_reflection("foo") def test_edit_reflection(client: TestClient): - dummyHkl.ubcalc.add_reflection([0, 0, 1], Position(7, 0, 10, 0, 0, 0), 12, "foo") + dummy_hkl.ubcalc.add_reflection([0, 0, 1], Position(7, 0, 10, 0, 0, 0), 12, "foo") response = client.patch( "/ub/test/reflection", json={ "energy": 13, - "tagOrIdx": "foo", + "tag_or_idx": "foo", }, ) - reflection = dummyHkl.ubcalc.get_reflection("foo") + reflection = dummy_hkl.ubcalc.get_reflection("foo") assert response.status_code == 200 assert reflection.energy == 13 - dummyHkl.ubcalc.del_reflection("foo") + dummy_hkl.ubcalc.del_reflection("foo") def test_delete_reflection(client: TestClient): - dummyHkl.ubcalc.add_reflection([0, 0, 1], Position(7, 0, 10, 0, 0, 0), 12, "foo") - response = client.delete("/ub/test/reflection", json={"tagOrIdx": "foo"}) + dummy_hkl.ubcalc.add_reflection([0, 0, 1], Position(7, 0, 10, 0, 0, 0), 12, "foo") + response = client.delete("/ub/test/reflection", json={"tag_or_idx": "foo"}) assert response.status_code == 200 with pytest.raises(Exception): - dummyHkl.ubcalc.get_reflection("foo") + dummy_hkl.ubcalc.get_reflection("foo") def test_edit_or_delete_reflection_fails_for_non_existing_reflection( client: TestClient, ): - editResponse = client.patch( + edit_response = client.patch( "/ub/test/reflection", json={ "energy": 13, - "tagOrIdx": "foo", + "tag_or_idx": "foo", }, ) - deleteResponse = client.delete( + delete_response = client.delete( "/ub/test/reflection", - json={"tagOrIdx": "foo"}, + json={"tag_or_idx": "foo"}, ) - assert editResponse.status_code == codes.get_reflection - assert deleteResponse.status_code == codes.get_reflection + assert edit_response.status_code == Codes.GET_REFLECTION + assert delete_response.status_code == Codes.GET_REFLECTION def test_add_orientation(client: TestClient): @@ -99,21 +99,21 @@ def test_add_orientation(client: TestClient): ) assert response.status_code == 200 - assert dummyHkl.ubcalc.get_orientation("bar") + assert dummy_hkl.ubcalc.get_orientation("bar") - dummyHkl.ubcalc.del_orientation("bar") + dummy_hkl.ubcalc.del_orientation("bar") def test_edit_orientation(client: TestClient): - dummyHkl.ubcalc.add_orientation([0, 0, 1], [0, 0, 1], None, "bar") + dummy_hkl.ubcalc.add_orientation([0, 0, 1], [0, 0, 1], None, "bar") response = client.patch( "/ub/test/orientation", json={ "xyz": [1, 1, 0], - "tagOrIdx": "bar", + "tag_or_idx": "bar", }, ) - orientation = dummyHkl.ubcalc.get_orientation("bar") + orientation = dummy_hkl.ubcalc.get_orientation("bar") assert response.status_code == 200 @@ -121,38 +121,38 @@ def test_edit_orientation(client: TestClient): assert orientation.y == 1 assert orientation.z == 0 - dummyHkl.ubcalc.del_orientation("bar") + dummy_hkl.ubcalc.del_orientation("bar") def test_delete_orientation(client: TestClient): - dummyHkl.ubcalc.add_orientation([0, 0, 1], [0, 0, 1], None, "bar") + dummy_hkl.ubcalc.add_orientation([0, 0, 1], [0, 0, 1], None, "bar") response = client.delete( "/ub/test/orientation", - json={"tagOrIdx": "bar"}, + json={"tag_or_idx": "bar"}, ) assert response.status_code == 200 with pytest.raises(Exception): - dummyHkl.ubcalc.get_orientation("bar") + dummy_hkl.ubcalc.get_orientation("bar") def test_edit_or_delete_orientation_fails_for_non_existing_orientation( client: TestClient, ): - editResponse = client.patch( + edit_response = client.patch( "/ub/test/orientation", json={ "xyz": [1, 1, 0], - "tagOrIdx": "bar", + "tag_or_idx": "bar", }, ) - deleteResponse = client.delete( + delete_response = client.delete( "/ub/test/orientation", - json={"tagOrIdx": "bar"}, + json={"tag_or_idx": "bar"}, ) - assert editResponse.status_code == codes.get_orientation - assert deleteResponse.status_code == codes.get_orientation + assert edit_response.status_code == Codes.GET_ORIENTATION + assert delete_response.status_code == Codes.GET_ORIENTATION def test_set_lattice(client: TestClient): @@ -162,22 +162,22 @@ def test_set_lattice(client: TestClient): ) assert response.status_code == 200 - assert dummyHkl.ubcalc.crystal + assert dummy_hkl.ubcalc.crystal def test_set_lattice_fails_for_empty_data(client: TestClient): - responseWithNoInput = client.patch( + response_with_no_input = client.patch( "/ub/test/lattice", json={}, ) - responseWithWrongInput = client.patch( + response_with_wrong_input = client.patch( "/ub/test/lattice", json={"unknown": "fields"}, ) - assert responseWithWrongInput.status_code == codes.check_params_not_empty - assert responseWithNoInput.status_code == codes.check_params_not_empty + assert response_with_wrong_input.status_code == Codes.CHECK_PARAMS_NOT_EMPTY + assert response_with_no_input.status_code == Codes.CHECK_PARAMS_NOT_EMPTY def test_modify_property(client: TestClient): @@ -187,7 +187,7 @@ def test_modify_property(client: TestClient): ) assert response.status_code == 200 - assert np.all(dummyHkl.ubcalc.n_hkl == np.transpose([[0, 0, 1]])) + assert np.all(dummy_hkl.ubcalc.n_hkl == np.transpose([[0, 0, 1]])) def test_modify_non_existent_property(client: TestClient): @@ -195,4 +195,4 @@ def test_modify_non_existent_property(client: TestClient): "/ub/test/silly_property", json=[0, 0, 1], ) - assert response.status_code == codes.check_property_is_valid + assert response.status_code == Codes.CHECK_PROPERTY_IS_VALID