diff --git a/docs/docs/api-reference/analysis.md b/docs/docs/api-reference/analysis.md new file mode 100644 index 00000000..ab949729 --- /dev/null +++ b/docs/docs/api-reference/analysis.md @@ -0,0 +1 @@ +::: easydynamics.analysis diff --git a/docs/docs/api-reference/index.md b/docs/docs/api-reference/index.md index 6e4cfb8d..7c211941 100644 --- a/docs/docs/api-reference/index.md +++ b/docs/docs/api-reference/index.md @@ -7,6 +7,14 @@ icon: material/code-braces-box This section contains the reference detailing the functions and modules available in EasyDynamics. -- [convolution](convolution.md) – Contains ... -- [sample_model](sample_model.md) – Handles ... -- [utils](utils.md) – Miscellaneous utility functions for ... +- [convolution](convolution.md) – Handles convolution of the sample + model with the instrument resolution. +- [experiment] (experiment.md) - Load, manage and visualize experimental + data. +- [sample_model](sample_model.md) – All modelling in EasyDynamics: The + scattering from the sample, including individual model components and + diffusion models, background, resolution and instrument. +- [analysis] (analysis.md) - Analysing experimental data by fitting a + sample model to experimental data, optionally convoluted with a + resolution model and adding a background. +- [utils](utils.md) – Miscellaneous utility functions for EasyDynamics. diff --git a/pixi.lock b/pixi.lock index 2e77e94b..1a38c4ea 100644 --- a/pixi.lock +++ b/pixi.lock @@ -80,7 +80,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -335,7 +335,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -590,7 +590,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -838,7 +838,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -1106,7 +1106,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/f7/7c/347280982982383621d29b8c544cf497ae07ac41e44b1ca4903024131f55/coverage-7.13.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -1362,7 +1362,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/b4/9b/77baf488516e9ced25fc215a6f75d803493fc3f6a1a1227ac35697910c2a/coverage-7.13.1-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -1618,7 +1618,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/d7/cd/7ab01154e6eb79ee2fab76bf4d89e94c6648116557307ee4ebbb85e5c1bf/coverage-7.13.1-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -1867,7 +1867,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/27/56/c216625f453df6e0559ed666d246fcbaaa93f3aa99eaa5080cea1229aa3d/coverage-7.13.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -2136,7 +2136,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -2391,7 +2391,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -2646,7 +2646,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -2894,7 +2894,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b8/01/74922a1c552137c05a41fee0c61153753dddc9117d19c7c5902c146c25ab/copier-9.11.3-py3-none-any.whl - - pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 + - pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 - pypi: https://files.pythonhosted.org/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f2/f2/728f041460f1b9739b85ee23b45fa5a505962ea11fd85bdbe2a02b021373/darkdetect-0.8.0-py3-none-any.whl @@ -4134,9 +4134,9 @@ packages: - validate-pyproject[all] ; extra == 'dev' - versioningit ; extra == 'dev' requires_python: '>=3.11' -- pypi: git+https://github.com/easyscience/corelib.git#ac01d891e271c7e2e5044da69b9ecd7b7114f0c3 +- pypi: git+https://github.com/easyscience/corelib.git#59d787b5158c6d72e0b4aa3cedd5e24f7fa61c56 name: easyscience - version: 2.1.0 + version: 2.2.0 requires_dist: - asteval - bumps diff --git a/src/easydynamics/analysis/analysis.py b/src/easydynamics/analysis/analysis.py index cee393b1..5332215b 100644 --- a/src/easydynamics/analysis/analysis.py +++ b/src/easydynamics/analysis/analysis.py @@ -35,8 +35,8 @@ class Analysis(AnalysisBase): instrument_model (InstrumentModel | None): The InstrumentModel associated with this Analysis. If None, a default InstrumentModel is created. - extra_parameters (Parameter | list[Parameter] | None): - Extra parameters to be included in the analysis for advanced + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced users. If None, no extra parameters are added. Attributes: @@ -53,7 +53,7 @@ class Analysis(AnalysisBase): temperature (Parameter | None): The temperature from the associated SampleModel, if available. extra_parameters (list[Parameter]): The extra parameters - included in this Analysis. + included in this Analysis. """ def __init__( @@ -65,6 +65,25 @@ def __init__( instrument_model: InstrumentModel | None = None, extra_parameters: Parameter | list[Parameter] | None = None, ): + """Initialize an Analysis object. + + Args: + display_name (str): Display name of the analysis. + unique_name (str or None): Unique name of the analysis. If + None, a unique name is automatically generated. + experiment (Experiment | None): The Experiment associated + with this Analysis. If None, a default Experiment is + created. + sample_model (SampleModel | None): The SampleModel + associated with this Analysis. If None, a default + SampleModel is created. + instrument_model (InstrumentModel | None): The + InstrumentModel associated with this Analysis. If None, + a default InstrumentModel is created. + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced + users. If None, no extra parameters are added. + """ # Avoid triggering updates before the object is fully # initialized @@ -138,7 +157,7 @@ def calculate( Args: Q_index (int or None): Index of the Q value to calculate - for. If None, calculate for all Q values. + for. If None, calculate for all Q values. Returns: list[np.ndarray] | np.ndarray: If Q_index is None, returns @@ -173,9 +192,9 @@ def fit( independently. Ignored if fit_method is "simultaneous". Default is None. - Returns: Fit results, which may be a list of FitResults if - fitting independently, or a single FitResults object if - fitting simultaneously. + Returns: + FitResults: a list of FitResults if fitting independently, + or a single FitResults object if fitting simultaneously. Raises: ValueError: If fit_method is not "independent" or @@ -215,13 +234,13 @@ def plot_data_and_model( Args: Q_index (int or None): Index of the Q value to plot. If - None, plot all Q values. Default is None. + None, plot all Q values. Default is None. plot_components (bool): Whether to plot the individual components. Default is True. add_background (bool): Whether to add background components to the sample model components when plotting. Default is True. - **kwargs: Additional keyword arguments passed to plopp + **kwargs (Any): Additional keyword arguments passed to plopp for customizing the plot. Raises: @@ -366,11 +385,11 @@ def plot_parameters( """Plot fitted parameters as a function of Q. Args: - names (str | list[str] | None): Name(s) of the - parameter(s) to plot. If None, plots all parameters. - kwargs: Additional keyword arguments passed to plopp.slicer for - customizing the plot (e.g., title, linestyle, marker, - color). + names (str | list[str] | None): Name(s) of the parameter(s) + to plot. If None, plots all parameters. + kwargs (Any): Additional keyword arguments passed to + plopp.slicer for customizing the plot (e.g., title, + linestyle, marker, color). Returns: InteractiveFigure: A Plopp InteractiveFigure containing the @@ -523,7 +542,7 @@ def _create_model_array(self) -> sc.DataArray: Returns: sc.DataArray: A DataArray containing the model values, with - dimensions "Q" and "energy". + dimensions "Q" and "energy". """ model = sc.array(dims=['Q', 'energy'], values=self.calculate()) @@ -547,7 +566,7 @@ def _create_components_dataset(self, add_background: bool = True) -> sc.Dataset: Returns: sc.Dataset: A scipp Dataset where each entry is a component - of the model, with dimensions "Q". + of the model, with dimensions "Q". """ if not isinstance(add_background, bool): raise TypeError('add_background must be True or False.') diff --git a/src/easydynamics/analysis/analysis1d.py b/src/easydynamics/analysis/analysis1d.py index 07fdf6ec..54bdab91 100644 --- a/src/easydynamics/analysis/analysis1d.py +++ b/src/easydynamics/analysis/analysis1d.py @@ -38,8 +38,8 @@ class Analysis1d(AnalysisBase): Q_index (int | None): The Q index to analyze. If None, the analysis will not be able to calculate or fit until a Q index is set. - extra_parameters (Parameter | list[Parameter] | None): - Extra parameters to be included in the analysis for advanced + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced users. If None, no extra parameters are added. Attributes: @@ -57,7 +57,7 @@ class Analysis1d(AnalysisBase): associated SampleModel, if available. Q_index (int | None): The Q index being analyzed. extra_parameters (list[Parameter]): The extra parameters - included in this Analysis. + included in this Analysis. """ def __init__( @@ -70,6 +70,28 @@ def __init__( Q_index: int | None = None, extra_parameters: Parameter | list[Parameter] | None = None, ): + """Initialize a Analysis1d. + + Args: + display_name (str): Display name of the analysis. + unique_name (str or None): Unique name of the analysis. If + None, a unique name is automatically generated. + experiment (Experiment | None): The Experiment associated + with this Analysis. If None, a default Experiment is + created. + sample_model (SampleModel | None): The SampleModel + associated with this Analysis. If None, a default + SampleModel is created. + instrument_model (InstrumentModel | None): The + InstrumentModel associated with this Analysis. If None, + a default InstrumentModel is created. + Q_index (int | None): The Q index to analyze. If None, the + analysis will not be able to calculate or fit until a + Q index is set. + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced + users. If None, no extra parameters are added. + """ super().__init__( display_name=display_name, unique_name=unique_name, @@ -96,7 +118,7 @@ def Q_index(self) -> int | None: """Get the Q index associated with this Analysis. Returns: - Experiment: The Experiment associated with this Analysis. + int | None: The Q index associated with this Analysis. """ return self._Q_index @@ -189,8 +211,9 @@ def as_fit_function(self, x=None, **kwargs) -> callable: calculated model. Args: - x: Ignored. The energy grid is taken from the experiment. - kwargs: Ignored. Included for compatibility with the + x (Any): Ignored. The energy grid is taken from the + experiment. + kwargs (dict): Ignored. Included for compatibility with the EasyScience fitter. """ @@ -203,7 +226,7 @@ def get_all_variables(self) -> list[DescriptorNumber]: """Get all variables used in the analysis. Returns: - List[Descriptor]: A list of all variables. + list[DescriptorNumber]: A list of all variables. """ variables = self.sample_model.get_all_variables(Q_index=self.Q_index) @@ -231,7 +254,7 @@ def plot_data_and_model( components of the model. Default is True. add_background (bool): Whether to add the background to the model prediction when plotting individual components. - kwargs: Keyword arguments to pass to the plotting + kwargs (dict): Keyword arguments to pass to the plotting function. Returns: @@ -327,14 +350,13 @@ def _evaluate_components( convolution (for background). Args: - components (ComponentCollection | ModelComponent): - The components to evaluate. + components (ComponentCollection | ModelComponent): The + components to evaluate. convolver (Convolution | None): An optional Convolution object to use for convolution. If None, a new Convolution object will be created if convolve is True. - convolve (bool): - Whether to perform convolution with the resolution. - Default is True. + convolve (bool): Whether to perform convolution with the + resolution. Default is True. """ Q_index = self._require_Q_index() @@ -541,7 +563,7 @@ def _create_components_dataset_single_Q( Returns: dict[str, sc.DataArray]: A dictionary of component names to - their corresponding sc.DataArrays. + their corresponding sc.DataArrays. """ scipp_arrays = {} diff --git a/src/easydynamics/analysis/analysis_base.py b/src/easydynamics/analysis/analysis_base.py index 07136062..24be2e28 100644 --- a/src/easydynamics/analysis/analysis_base.py +++ b/src/easydynamics/analysis/analysis_base.py @@ -33,8 +33,8 @@ class AnalysisBase(EasyScienceModelBase): instrument_model (InstrumentModel | None): The InstrumentModel associated with this Analysis. If None, a default InstrumentModel is created. - extra_parameters (Parameter | list[Parameter] | None): - Extra parameters to be included in the analysis for advanced + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced users. If None, no extra parameters are added. Attributes: @@ -51,7 +51,7 @@ class AnalysisBase(EasyScienceModelBase): temperature (Parameter | None): The temperature from the associated SampleModel, if available. extra_parameters (list[Parameter]): The extra parameters - included in this Analysis. + included in this Analysis. """ def __init__( @@ -63,6 +63,34 @@ def __init__( instrument_model: InstrumentModel | None = None, extra_parameters: Parameter | list[Parameter] | None = None, ): + """Initialize the AnalysisBase. + + Args: + display_name (str): Display name of the analysis. + unique_name (str or None): Unique name of the analysis. If + None, a unique name is automatically generated. + experiment (Experiment | None): The Experiment associated + with this Analysis. If None, a default Experiment is + created. + sample_model (SampleModel | None): The SampleModel + associated with this Analysis. If None, a default + SampleModel is created. + instrument_model (InstrumentModel | None): The + InstrumentModel associated with this Analysis. If None, + a default InstrumentModel is created. + extra_parameters (Parameter | list[Parameter] | None): Extra + parameters to be included in the analysis for advanced + users. If None, no extra parameters are added. + + Raises: + TypeError: If experiment is not an Experiment or None. + TypeError: If sample_model is not a SampleModel or None. + TypeError: If instrument_model is not an InstrumentModel or + None. + TypeError: If extra_parameters is not a Parameter, a list of + Parameters, or None. + """ + super().__init__(display_name=display_name, unique_name=unique_name) if experiment is None: @@ -257,18 +285,20 @@ def extra_parameters(self, value: Parameter | list[Parameter]) -> None: Args: value (Parameter | list[Parameter]): The extra parameters to - include in this Analysis. + include in this Analysis. Raises: - TypeError: If value is not a Parameter or a list of - Parameters. + TypeError: If value is not a Parameter, a list of + Parameters, or None. """ if isinstance(value, Parameter): self._extra_parameters = [value] elif isinstance(value, list) and all(isinstance(p, Parameter) for p in value): self._extra_parameters = value + elif value is None: + self._extra_parameters = [] else: - raise TypeError('extra_parameters must be a Parameter or a list of Parameters.') + raise TypeError('extra_parameters must be a Parameter, a list of Parameters, or None.') ############# # Other methods diff --git a/src/easydynamics/convolution/analytical_convolution.py b/src/easydynamics/convolution/analytical_convolution.py index 031d5975..a637e8fd 100644 --- a/src/easydynamics/convolution/analytical_convolution.py +++ b/src/easydynamics/convolution/analytical_convolution.py @@ -22,14 +22,18 @@ class AnalyticalConvolution(ConvolutionBase): Possible analytical convolutions are any combination of delta functions, Gaussians, Lorentzians and Voigt profiles. + Args: - energy : np.ndarray or scipp.Variable - 1D array of energy values where the convolution is - evaluated. - sample_components : ComponentCollection or ModelComponent - The sample model to be convolved. - resolution_components : ComponentCollection or ModelComponent + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + sample model to be convolved. + resolution_components (ComponentCollection | ModelComponent): The resolution model to convolve with. + energy_offset (Numeric | Parameter, optional): An offset to + shift the energy values by. Default is 0.0. + energy_unit (str | sc.Unit, optional): The unit of the energy. + Default is 'meV'. """ # Mapping of supported component type pairs to convolution methods. @@ -51,6 +55,20 @@ def __init__( resolution_components: ComponentCollection | ModelComponent | None = None, energy_offset: Numeric | Parameter = 0.0, ): + """Initialize an AnalyticalConvolution. + + Args: + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): + The sample model to be convolved. + resolution_components (ComponentCollection | + ModelComponent): The resolution model to convolve with. + energy_offset (Numeric | Parameter, optional): An offset to + shift the energy values by. Default is 0.0. + energy_unit (str | sc.Unit, optional): The unit of the + energy. Default is 'meV'. + """ super().__init__( energy=energy, energy_unit=energy_unit, @@ -68,15 +86,14 @@ def convolution( functions, Gaussians, Lorentzians and Voigt profiles. Returns: - np.ndarray - The convolution of the sample_components and resolution_ - components values evaluated at energy. + np.ndarray: The convolution of the sample_components and + resolution_components values evaluated at self.energy. Raises: - ValueError - If resolution_components contains delta functions. - ValueError - If component pair cannot be handled analytically. + ValueError: If resolution_components contains delta + functions. + ValueError: If component pair cannot be handled + analytically. """ sample_components = self.sample_components.components @@ -101,37 +118,48 @@ def _convolute_analytic_pair( sample_component: ModelComponent, resolution_component: ModelComponent, ) -> np.ndarray: - """Analytic convolution for component pair (sample_component, - resolution_component). The convolution of two gaussian - components results in another gaussian component with width - sqrt(w1^2 + w2^2). The convolution of two lorentzian components - results in another lorentzian component with width w1 + w2. The - convolution of a gaussian and a lorentzian results in a voigt - profile. The convolution of a gaussian and a voigt profile - results in another voigt profile, with the lorentzian width - unchanged and the gaussian widths summed in quadrature. The - convolution of a lorentzian and a voigt profile results in - another voigt profile, with the gaussian width unchanged and the - lorentzian widths summed. The convolution of two voigt profiles - results in another voigt profile, with the gaussian widths - summed in quadrature and the lorentzian widths summed. The - convolution of a delta function with any component or + r"""Analytic convolution for component pair (sample_component, + resolution_component). + + The convolution of two Gaussian components results in another + Gaussian component with width $\sqrt{w_1^2 + w_2^2}$. + + The convolution of two Lorentzian components results in another + Lorentzian component with width $w_1 + w_2$. + + The convolution of a Gaussian and a Lorentzian results in a + Voigt profile. + + The convolution of a Gaussian and a Voigt profile results in + another Voigt profile, with the Lorentzian width unchanged and + the Gaussian widths summed in quadrature. + + The convolution of a Lorentzian and a Voigt profile results in + another Voigt profile, with the Gaussian width unchanged and the + Lorentzian widths summed. + + The convolution of two Voigt profiles results in another Voigt + profile, with the Gaussian widths summed in quadrature and the + Lorentzian widths summed. + + The convolution of a delta function with any component or ComponentCollection results in the same component or - ComponentCollection shifted by the delta center. All areas are - multiplied. + ComponentCollection shifted by the delta center. + + All areas are multiplied in the convolution. Args: - sample_component : ModelComponent - The sample component to be convolved. - resolution_component : ModelComponent - The resolution component to convolve with. + sample_component (ModelComponent): The sample component to + be convolved. + resolution_component (ModelComponent): The resolution + component to convolve with. Returns: np.ndarray: The convolution result Raises: - ValueError: - If the component pair cannot be handled analytically. + ValueError: If the component pair cannot be handled + analytically. """ if isinstance(resolution_component, DeltaFunction): @@ -184,13 +212,13 @@ def _convolute_delta_any( multiplied. Args: - sample_component : DeltaFunction - The sample component to be convolved. - resolution_components : ComponentCollection | ModelComponent - The resolution model to convolve with. + sample_component (DeltaFunction): The sample component to + be convolved. + resolution_components (ComponentCollection | ModelComponent) + : The resolution model to convolve with. + Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ return sample_component.area.value * resolution_components.evaluate( self.energy_with_offset.values - sample_component.center.value @@ -201,20 +229,18 @@ def _convolute_gaussian_gaussian( sample_component: Gaussian, resolution_component: Gaussian, ) -> np.ndarray: - """Convolution of two Gaussian components results in another - Gaussian component with width sqrt(w1^2 + w2^2). The areas are - multiplied. + r"""Convolution of two Gaussian components results in another + Gaussian component with width $\sqrt{w_1^2 + w_2^2}$. The areas + are multiplied. Args: - sample_component : Gaussian - The sample Gaussian component to be convolved. - resolution_component : Gaussian - The resolution Gaussian component to convolve with. + sample_component (Gaussian): The sample Gaussian component + to be convolved. + resolution_component (Gaussian): The resolution Gaussian + component to convolve with. Returns: - np.ndarray - - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ width = np.sqrt(sample_component.width.value**2 + resolution_component.width.value**2) @@ -234,14 +260,13 @@ def _convolute_gaussian_lorentzian( profile. The areas are multiplied. Args: - sample_component : Gaussian - The sample Gaussian component to be convolved. - resolution_component : Lorentzian - The resolution Lorentzian component to convolve with. + sample_component (Gaussian): The sample Gaussian component + to be convolved. + resolution_component (Lorentzian): The resolution Lorentzian + component to convolve with. Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ center = sample_component.center.value + resolution_component.center.value area = sample_component.area.value * resolution_component.area.value @@ -264,14 +289,13 @@ def _convolute_gaussian_voigt( are multiplied. Args: - sample_component : Gaussian - The sample Gaussian component to be convolved. - resolution_component : Voigt - The resolution Voigt component to convolve with. + sample_component (Gaussian): The sample Gaussian component + to be convolved. + resolution_component (Voigt): The resolution Voigt component + to convolve with. Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ area = sample_component.area.value * resolution_component.area.value @@ -295,18 +319,18 @@ def _convolute_lorentzian_lorentzian( sample_component: Lorentzian, resolution_component: Lorentzian, ) -> np.ndarray: - """Convolution of two Lorentzian components results in another - Lorentzian component with width w1 + w2. The areas are + r"""Convolution of two Lorentzian components results in another + Lorentzian component with width $w_1 + w_2$. The areas are multiplied. Args: - sample_component : Lorentzian - The sample Lorentzian component to be convolved. - resolution_component : Lorentzian - The resolution Lorentzian component to convolve with. + sample_component (Lorentzian): The sample Lorentzian + component to be convolved. + resolution_component (Lorentzian): The resolution Lorentzian + component to convolve with. + Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ area = sample_component.area.value * resolution_component.area.value @@ -326,15 +350,16 @@ def _convolute_lorentzian_voigt( The Gaussian width remains unchanged, while the Lorentzian widths are summed. + The areas are multiplied. + Args: - sample_component : Lorentzian - The sample Lorentzian component to be convolved. - resolution_component : Voigt - The resolution Voigt component to convolve with. + sample_component (Lorentzian): The sample Lorentzian + component to be convolved. + resolution_component (Voigt): The resolution Voigt component + to convolve with. Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ area = sample_component.area.value * resolution_component.area.value @@ -364,14 +389,15 @@ def _convolute_voigt_voigt( The Gaussian widths are summed in quadrature, while the Lorentzian widths are summed. The areas are multiplied. + Args: - sample_component : Voigt - The sample Voigt component to be convolved. - resolution_component : Voigt - The resolution Voigt component to convolve with. + sample_component (Voigt): The sample Voigt component to be + convolved. + resolution_component (Voigt): The resolution Voigt component + to convolve with. + Returns: - np.ndarray - The evaluated convolution values at self.energy. + np.ndarray: The evaluated convolution values at self.energy. """ area = sample_component.area.value * resolution_component.area.value @@ -397,20 +423,28 @@ def _gaussian_eval( center: float, width: float, ) -> np.ndarray: - """Evaluate a Gaussian function. y = (area/(sqrt(2pi) * - width))*exp(-0.5*((x-center) / width)^2) All checks are handled - in the calling function. + r"""Evaluate a Gaussian function. + + $$ + I(x) = \frac{A}{\sigma \sqrt{2\pi}} + \exp\left( + -\frac{1}{2} + \left(\frac{x - x_0}{\sigma}\right)^2 + \right) + $$ + + where $A$ is the area, $x_0$ is the center, and $\sigma$ is the + width. + + All checks are handled in the calling function. Args: - area : float - The area under the Gaussian curve. - center : float - The center of the Gaussian. - width : float - The width (sigma) of the Gaussian. + area (float): The area under the Gaussian curve. + center (float): The center of the Gaussian. + width (float): The width (sigma) of the Gaussian. + Returns: - np.ndarray - The evaluated Gaussian values at self.energy. + np.ndarray: The evaluated Gaussian values at self.energy. """ normalization = 1 / (np.sqrt(2 * np.pi) * width) @@ -419,21 +453,25 @@ def _gaussian_eval( return area * normalization * np.exp(exponent) def _lorentzian_eval(self, area: float, center: float, width: float) -> np.ndarray: - """ + r""" Evaluate a Lorentzian function. - y = (area * width / pi) / ((x - center)^2 + width^2). + + $$ + I(x) = \frac{A}{\\pi} \frac{\Gamma}{(x - x_0)^2 + \Gamma^2}, + $$ + + where $A$ is the area, $x_0$ is the center, and $\\Gamma$ is + the half width at half maximum (HWHM). + All checks are handled in the calling function. Args: - area : float - The area under the Lorentzian. - center : float - The center of the Lorentzian. - width : float - The width (HWHM) of the Lorentzian. + area (float): The area under the Lorentzian. + center (float): The center of the Lorentzian. + width (float): The width (HWHM) of the Lorentzian. + Returns: - np.ndarray - The evaluated Lorentzian values at self.energy. + np.ndarray: The evaluated Lorentzian values at self.energy. """ normalization = width / np.pi @@ -452,17 +490,16 @@ def _voigt_eval( voigt_profile. Args: - area : float - The area under the Voigt profile. - center : float - The center of the Voigt profile. - gaussian_width : float - The Gaussian width (sigma) of the Voigt profile. - lorentzian_width : float - The Lorentzian width (HWHM) of the Voigt profile. + area (float): The area under the Voigt profile. + center (float): The center of the Voigt profile. + gaussian_width (float): The Gaussian width (sigma) of the + Voigt profile. + lorentzian_width (float): The Lorentzian width (HWHM) of the + Voigt profile. + Returns: - np.ndarray - The evaluated Voigt profile values at self.energy. + np.ndarray: The evaluated Voigt profile values at + self.energy. """ return area * voigt_profile( diff --git a/src/easydynamics/convolution/convolution.py b/src/easydynamics/convolution/convolution.py index 46c4f0c6..b799d60f 100644 --- a/src/easydynamics/convolution/convolution.py +++ b/src/easydynamics/convolution/convolution.py @@ -20,40 +20,61 @@ class Convolution(NumericalConvolutionBase): """Convolution class that combines analytical and numerical convolution methods to efficiently perform convolutions of - ComponentCollections with ResolutionComponents. Supports analytical - convolution for pairs of analytical model components (DeltaFunction, - Gaussian, Lorentzian, Voigt), while using numerical convolution for - other components. If temperature is provided, detailed balance - correction is applied to the sample model. In this case, all - convolutions are handled numerically. Includes a setting to - normalize the detailed balance correction. Includes optional - upsampling and extended range to improve accuracy of the numerical - convolutions. Also warns about numerical instabilities if peaks are - very wide or very narrow. + ComponentCollections with ResolutionComponents. + + Supports analytical convolution for pairs of analytical model + components (DeltaFunction, Gaussian, Lorentzian, Voigt), while + using numerical convolution for other components. + If temperature is provided, detailed balance correction is applied + to the sample model. In this case, all convolutions are handled + numerically. + Includes a setting to normalize the detailed balance correction. + Includes optional upsampling and extended range to improve accuracy + of the numerical convolutions. Also warns about numerical + instabilities if peaks are very wide or very narrow. Args: - energy : np.ndarray or scipp.Variable - 1D array of energy values where the convolution is evaluated. - sample_components : ComponentCollection or ModelComponent - The sample components to be convolved. - resolution_components : ComponentCollection or ModelComponent - The resolution components to convolve with. - upsample_factor : int, optional - The factor by which to upsample the input data before - convolution. Default is 5. - extension_factor : float, optional - The factor by which to extend the input data range before - convolution. Default is 0.2. - temperature : Parameter, float, or None, optional - The temperature to use for detailed balance correction. - Default is None. - temperature_unit : str or sc.Unit, optional - The unit of the temperature parameter. Default is 'K'. - energy_unit : str or sc.Unit, optional - The unit of the energy. Default is 'meV'. - normalize_detailed_balance : bool, optional - Whether to normalize the detailed balance correction. - Default is True. + energy (np.ndarray | scipp.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + sample components to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution components to convolve with. + upsample_factor (int | None): The factor by which to upsample + the input data before convolution. Default is 5. + extension_factor (float | None): The factor by which to + extend the input data range before convolution. Default is + 0.2. + temperature (Parameter | float | None): The + temperature to use for detailed balance correction. Default + is None. + temperature_unit (str | sc.Unit | None): The unit of the + temperature parameter. Default is 'K'. + energy_unit (str | sc.Unit | None): The unit of the energy. + Default is 'meV'. + normalize_detailed_balance (bool | None): Whether to + normalize the detailed balance correction. Default is True. + + Attributes: + energy (scipp.Variable): 1D array of energy values where the + convolution is evaluated. + sample_components (ComponentCollection): The sample components + to be convolved. + resolution_components (ComponentCollection): The resolution + components to convolve with. + energy_offset (Parameter): Energy offset to apply to the energy + values before convolution. + upsample_factor (int): The factor by which to upsample the input + data before convolution. + extension_factor (float): The factor by which to extend the + input data range before convolution. + temperature (Parameter | None): The temperature to use for + detailed balance correction. + temperature_unit (str | sc.Unit): The unit of the temperature + parameter. + energy_unit (str | sc.Unit): The unit of the energy. + normalize_detailed_balance (bool): Whether to normalize the + detailed balance correction. """ # When these attributes are changed, the convolution plan @@ -84,6 +105,34 @@ def __init__( energy_unit: str | sc.Unit = 'meV', normalize_detailed_balance: bool = True, ): + """Initialize the Convolution class. + + Args: + energy (np.ndarray | scipp.Variable): 1D array of energy + values where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): + The sample components to be convolved. + resolution_components (ComponentCollection | + ModelComponent): The resolution components to convolve + with. + upsample_factor (int | None): The factor by which to + upsample the input data before convolution. Default is + 5. + extension_factor (float | None): The factor by which to + extend the input data range before convolution. Default + is 0.2. + temperature (Parameter | float | None): The + temperature to use for detailed balance correction. + Default is None. + temperature_unit (str | sc.Unit | None): The unit of the + temperature parameter. Default is 'K'. + energy_unit (str | sc.Unit | None): The unit of the energy. + Default is 'meV'. + normalize_detailed_balance (bool | None): Whether to + normalize the detailed balance correction. Default is + True. + """ + self._convolution_plan_is_valid = False self._reactions_enabled = False super().__init__( @@ -114,8 +163,7 @@ def convolution( components. Returns: - np.ndarray - The convolved values evaluated at energy. + np.ndarray: The convolved values evaluated at energy. """ if not self._convolution_plan_is_valid: self._build_convolution_plan() @@ -141,9 +189,8 @@ def _convolve_delta_functions(self) -> np.ndarray: applied to delta functions. Returns: - np.ndarray - The convolved values of the delta function components - evaluated at energy. + np.ndarray: The convolved values of the delta function c + components evaluated at energy. """ return sum( delta.area.value @@ -162,14 +209,14 @@ def _check_if_pair_is_analytic( handled analytically. Args: - sample_component : ModelComponent - The sample component to be convolved. - resolution_component : ModelComponent - The resolution component to convolve with. + sample_component (ModelComponent): The sample component to + be convolved. + resolution_component (ModelComponent): The resolution + component to convolve with. + Returns: - bool - True if the component pair can be handled analytically, - False otherwise. + bool: True if the component pair can be handled + analytically, False otherwise. """ if not isinstance(sample_component, ModelComponent): @@ -277,7 +324,7 @@ def _set_convolvers(self) -> None: self._numerical_convolver = None # Update some setters so the internal sample models are updated - def __setattr__(self, name, value): + def __setattr__(self, name, value) -> None: """Custom setattr to invalidate convolution plan on relevant attribute changes, and build a new plan. diff --git a/src/easydynamics/convolution/convolution_base.py b/src/easydynamics/convolution/convolution_base.py index 9f1799f5..5e69a4f4 100644 --- a/src/easydynamics/convolution/convolution_base.py +++ b/src/easydynamics/convolution/convolution_base.py @@ -15,14 +15,27 @@ class ConvolutionBase: base class has no convolution functionality. Args: - energy : np.ndarray or scipp.Variable - 1D array of energy values where the convolution is evaluated - sample_components : ComponentCollection or ModelComponent - The sample model to be convolved. - resolution_components : ComponentCollection or ModelComponent + energy (np.ndarray | scipp.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + sample model to be convolved. + resolution_components (ComponentCollection | ModelComponent): The resolution model to convolve with. - energy_unit : str or sc.Unit, optional - The unit of the energy. Default is 'meV'. + energy_unit (str | sc.Unit, optional): The unit of the energy. + Default is 'meV'. + energy_offset (Numeric | Parameter, optional): The energy offset + applied to the convolution. Default is 0.0. + + Attributes: + energy (scipp.Variable): 1D array of energy values where the + convolution is evaluated + sample_components (ComponentCollection | ModelComponent): The + sample model to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution model to convolve with. + energy_unit (str | sc.Unit): The unit of the energy. + energy_offset (Parameter): The energy offset applied to the + convolution. """ def __init__( @@ -33,6 +46,30 @@ def __init__( energy_unit: str | sc.Unit = 'meV', energy_offset: Numeric | Parameter = 0.0, ): + """Initialize the ConvolutionBase. + + Args: + energy (np.ndarray | scipp.Variable): 1D array of energy + values where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): + The sample model to be convolved. + resolution_components (ComponentCollection | + ModelComponent): The resolution model to convolve with. + energy_unit (str | sc.Unit, optional): The unit of the + energy. Default is 'meV'. + energy_offset (Numeric | Parameter, optional): The energy + offset applied to the convolution. Default is 0.0. + + Raises: + TypeError: If energy is not a numpy ndarray or a scipp + Variable. + TypeError: If energy_unit is not a string or scipp unit. + TypeError: If energy_offset is not a number or a Parameter. + TypeError: If sample_components is not a ComponentCollection + or ModelComponent. + TypeError: If resolution_components is not a + ComponentCollection or ModelComponent. + """ if isinstance(energy, Numeric): energy = np.array([float(energy)]) @@ -81,12 +118,17 @@ def __init__( @property def energy_offset(self) -> Parameter: - """Get the energy offset.""" + """Get the energy offset. + + Returns: + Parameter: The energy offset applied to the convolution. + """ return self._energy_offset @energy_offset.setter def energy_offset(self, energy_offset: Numeric | Parameter) -> None: """Set the energy offset. + Args: energy_offset : Number or Parameter The energy offset to apply to the convolution. @@ -105,7 +147,11 @@ def energy_offset(self, energy_offset: Numeric | Parameter) -> None: @property def energy_with_offset(self) -> sc.Variable: - """Get the energy with the offset applied.""" + """Get the energy with the offset applied. + + Returns: + sc.Variable: The energy values with the offset applied. + """ energy_with_offset = self.energy.copy() energy_with_offset.values = self.energy.values - self.energy_offset.value return energy_with_offset @@ -114,6 +160,13 @@ def energy_with_offset(self) -> sc.Variable: def energy_with_offset(self, value) -> None: """Energy with offset is a read-only property derived from energy and energy_offset. + + Args: + value: The value to set (ignored). + + Raises: + AttributeError: Always raised since energy_with_offset is + read-only. """ raise AttributeError( 'Energy with offset is a read-only property derived from energy and energy_offset.' @@ -121,16 +174,22 @@ def energy_with_offset(self, value) -> None: @property def energy(self) -> sc.Variable: - """Get the energy.""" + """Get the energy. + + Returns: + sc.Variable: The energy values where the convolution is + evaluated. + """ return self._energy @energy.setter def energy(self, energy: np.ndarray | sc.Variable) -> None: """Set the energy. + Args: energy (np.ndarray | scipp.Variable): 1D array of energy - values where the convolution is evaluated. + values where the convolution is evaluated. Raises: TypeError: If energy is not a numpy ndarray or a @@ -152,7 +211,11 @@ def energy(self, energy: np.ndarray | sc.Variable) -> None: @property def energy_unit(self) -> str: - """Get the energy unit.""" + """Get the energy unit. + + Returns: + str: The unit of the energy. + """ return self._energy_unit @energy_unit.setter @@ -168,8 +231,7 @@ def convert_energy_unit(self, energy_unit: str | sc.Unit) -> None: """Convert the energy and energy_offset to the specified unit. Args: - energy_unit : str or sc.Unit - The unit of the energy. + energy_unit (str | sc.Unit): The unit of the energy. Raises: TypeError: If energy_unit is not a string or scipp unit. @@ -197,19 +259,25 @@ def convert_energy_unit(self, energy_unit: str | sc.Unit) -> None: @property def sample_components(self) -> ComponentCollection | ModelComponent: - """Get the sample model.""" + """Get the sample model. + + Returns: + ComponentCollection or ModelComponent: The sample model to + be convolved. + """ return self._sample_components @sample_components.setter def sample_components(self, sample_components: ComponentCollection | ModelComponent) -> None: """Set the sample model. + Args: sample_components : ComponentCollection or ModelComponent The sample model to be convolved. Raises: TypeError: If sample_components is not a ComponentCollection - or ModelComponent. + or ModelComponent. """ if not isinstance(sample_components, (ComponentCollection, ModelComponent)): raise TypeError( @@ -222,7 +290,12 @@ def sample_components(self, sample_components: ComponentCollection | ModelCompon @property def resolution_components(self) -> ComponentCollection | ModelComponent: - """Get the resolution model.""" + """Get the resolution model. + + Returns: + ComponentCollection or ModelComponent: The resolution model + to be convolved. + """ return self._resolution_components @resolution_components.setter @@ -230,14 +303,15 @@ def resolution_components( self, resolution_components: ComponentCollection | ModelComponent ) -> None: """Set the resolution model. + Args: - resolution_components : ComponentCollection or - ModelComponent - The resolution model to convolve with. + resolution_components (ComponentCollection | ModelComponent) + : The resolution model to be convolved. Can be a + ComponentCollection or a single ModelComponent Raises: TypeError: If resolution_components is not a - ComponentCollection or ModelComponent. + ComponentCollection or ModelComponent. """ if not isinstance(resolution_components, (ComponentCollection, ModelComponent)): raise TypeError( diff --git a/src/easydynamics/convolution/energy_grid.py b/src/easydynamics/convolution/energy_grid.py index ab488753..c8b0c340 100644 --- a/src/easydynamics/convolution/energy_grid.py +++ b/src/easydynamics/convolution/energy_grid.py @@ -11,20 +11,17 @@ class EnergyGrid: """Container for the dense energy grid and related metadata. Attributes: - energy_dense : np.ndarray - The upsampled and extended energy array. - energy_dense_centered : np.ndarray - The centered version of energy_dense - (used for resolution evaluation). - energy_dense_step : float - The spacing of energy_dense + energy_dense (np.ndarray): The upsampled and extended energy + array. + energy_dense_centered (np.ndarray): The centered version of + energy_dense (used for resolution evaluation). + energy_dense_step (float): The spacing of energy_dense (used for width checks and normalization). - energy_span_dense : float - The total span of energy_dense. + energy_span_dense (float): The total span of energy_dense. (used for width checks). - energy_even_length_offset : float - The offset to apply if energy_dense has even length - (used for convolution alignment). + energy_even_length_offset (float): The offset to apply if + energy_dense has even length (used for convolution + alignment). """ energy_dense: np.ndarray diff --git a/src/easydynamics/convolution/numerical_convolution.py b/src/easydynamics/convolution/numerical_convolution.py index 1b8ca6d1..9738c58c 100644 --- a/src/easydynamics/convolution/numerical_convolution.py +++ b/src/easydynamics/convolution/numerical_convolution.py @@ -21,30 +21,47 @@ class NumericalConvolution(NumericalConvolutionBase): balance correction is applied to the sample model. Args: - energy : np.ndarray or scipp.Variable - 1D array of energy values where the convolution is evaluated. - sample_components : ComponentCollection or ModelComponent - The sample model to be convolved. - resolution_components : ComponentCollection or ModelComponent - The resolution model to convolve with. - upsample_factor : int, optional - The factor by which to upsample the input data - before convolution. - Default is 5. - extension_factor : float, optional - The factor by which to extend the input data range - before convolution. - Default is 0.2. - temperature : Parameter, float, or None, optional - The temperature to use for detailed balance correction. - Default is None. - temperature_unit : str or sc.Unit, optional - The unit of the temperature parameter. Default is 'K'. - energy_unit : str or sc.Unit, optional - The unit of the energy. Default is 'meV'. - normalize_detailed_balance : bool, optional - Whether to normalize the detailed balance correction. - Default is True. + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + sample model to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution model to convolve with. + upsample_factor (int, optional): The factor by which to upsample + the input data before convolution. Default is 5. + extension_factor (float, optional): The factor by which to + extend the input data range before convolution. Default is + 0.2. + temperature (Parameter | float | None, optional): The + temperature to use for detailed balance correction. Default + is None. + temperature_unit (str | sc.Unit, optional): The unit of the + temperature parameter. Default is 'K'. + energy_unit (str | sc.Unit, optional): The unit of the energy. + Default is 'meV'. + normalize_detailed_balance (bool, optional): Whether to + normalize the detailed balance correction. Default is True. + + Attributes: + energy (np.ndarray | sc.Variable): The energy values where the + convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + sample model to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution model to convolve with. + energy_offset (Parameter): The energy offset to apply to the + sample model before convolution. + upsample_factor (int): The factor by which to upsample the input + data before convolution. + extension_factor (float): The factor by which to extend the + input data range before convolution. + temperature (Parameter | float | None): The temperature to use + for detailed balance correction. + temperature_unit (str | sc.Unit): The unit of the temperature + parameter. + energy_unit (str | sc.Unit): The unit of the energy. + normalize_detailed_balance (bool): Whether to normalize the + detailed balance correction. """ def __init__( @@ -60,6 +77,42 @@ def __init__( energy_unit: str | sc.Unit = 'meV', normalize_detailed_balance: bool = True, ): + """Initialize the NumericalConvolution object. + + Args: + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): + The sample model to be convolved. + resolution_components (ComponentCollection | + ModelComponent): The resolution model to convolve with. + upsample_factor (int, optional): The factor by which to + upsample the input data before convolution. Default is + 5. + extension_factor (float, optional): The factor by which to + extend the input data range before convolution. Default + is 0.2. + temperature (Parameter | float | None, optional): The + temperature to use for detailed balance correction. + Default is None. + temperature_unit (str | sc.Unit, optional): The unit of the + temperature parameter. Default is 'K'. + energy_unit (str | sc.Unit, optional): The unit of the + energy. Default is 'meV'. + normalize_detailed_balance (bool, optional): Whether to + normalize the detailed balance correction. Default is + True. + + Raises: + TypeError: If temperature is not None, a number, or a + Parameter. + TypeError: If temperature_unit is not a string or sc.Unit. + TypeError: If upsample_factor is not a number or None. + ValueError: If upsample_factor is not greater than 1. + TypeError: If extension_factor is not a number. + ValueError: If extension_factor is negative. + TypeError: If normalize_detailed_balance is not a bool. + """ super().__init__( energy=energy, sample_components=sample_components, diff --git a/src/easydynamics/convolution/numerical_convolution_base.py b/src/easydynamics/convolution/numerical_convolution_base.py index 5a60f5d8..b1672a16 100644 --- a/src/easydynamics/convolution/numerical_convolution_base.py +++ b/src/easydynamics/convolution/numerical_convolution_base.py @@ -34,28 +34,44 @@ class NumericalConvolutionBase(ConvolutionBase): functionality. Args: - energy : np.ndarray or scipp.Variable - 1D array of energy values where the convolution is evaluated. - sample_components : ComponentCollection or ModelComponent - The components to be convolved. - resolution_components : ComponentCollection or ModelComponent - The resolution components to convolve with. - upsample_factor : int, optional - The factor by which to upsample the input data - before convolution. Default is 5. - extension_factor : float, optional - The factor by which to extend the input data range - before convolution. Default is 0.2. - temperature : Parameter, float, or None, optional - The temperature to use for detailed balance correction. - Default is None. - temperature_unit : str or sc.Unit, optional - The unit of the temperature parameter. Default is 'K'. - energy_unit : str or sc.Unit, optional - The unit of the energy. Default is 'meV'. - normalize_detailed_balance : bool, optional - Whether to normalize the detailed balance correction. - Default is True. + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + components to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution components to convolve with. + upsample_factor (int | None): The factor by which to upsample + the input data before convolution. Default is 5. + extension_factor (float | None): The factor by which to extend + the input data range before convolution. Default is 0.2. + temperature (Parameter | float | None): The temperature to use + for detailed balance correction. Default is None. + temperature_unit (str | sc.Unit): The unit of the temperature + parameter. Default is 'K'. + energy_unit (str | sc.Unit): The unit of the energy. Default is + 'meV'. + normalize_detailed_balance (bool): Whether to normalize the + detailed balance correction. Default is True. + + Attributes: + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): The + components to be convolved. + resolution_components (ComponentCollection | ModelComponent): + The resolution components to convolve with. + upsample_factor (int | None): The factor by which to upsample + the input data before convolution. + extension_factor (float | None): The factor by which to extend + the input data range before convolution. + temperature (Parameter | None): The temperature parameter for + detailed balance correction, or None if detailed balance is + disabled. + temperature_unit (str | sc.Unit): The unit of the temperature + parameter. + energy_unit (str | sc.Unit): The unit of the energy. + normalize_detailed_balance (bool): Whether to normalize the + detailed balance correction. """ def __init__( @@ -71,6 +87,41 @@ def __init__( energy_unit: str | sc.Unit = 'meV', normalize_detailed_balance: bool = True, ): + """Initialize the NumericalConvolutionBase. + + Args: + energy (np.ndarray | sc.Variable): 1D array of energy values + where the convolution is evaluated. + sample_components (ComponentCollection | ModelComponent): + The components to be convolved. + resolution_components (ComponentCollection | + ModelComponent): The resolution components to convolve + with. + upsample_factor (int | None): The factor by which to + upsample the input data before convolution. Default is + 5. + extension_factor (float | None): The factor by which to + extend the input data range before convolution. Default + is 0.2. + temperature (Parameter | float | None): The temperature to + use for detailed balance correction. Default is None. + temperature_unit (str | sc.Unit): The unit of the + temperature parameter. Default is 'K'. + energy_unit (str | sc.Unit): The unit of the energy. Default + is 'meV'. + normalize_detailed_balance (bool): Whether to normalize the + detailed balance correction. Default is True. + + Raises: + TypeError: If temperature is not None, a number, or a + Parameter. + TypeError: If temperature_unit is not a string or sc.Unit. + TypeError: If upsample_factor is not a number or None. + ValueError: If upsample_factor is not greater than 1. + TypeError: If extension_factor is not a number. + ValueError: If extension_factor is negative. + TypeError: If normalize_detailed_balance is not a bool. + """ super().__init__( energy=energy, sample_components=sample_components, @@ -100,19 +151,36 @@ def __init__( @ConvolutionBase.energy.setter def energy(self, energy: np.ndarray) -> None: + """Set the energy array and recreate the dense grid. + + Args: + energy (np.ndarray): The new energy array. + """ ConvolutionBase.energy.fset(self, energy) # Recreate dense grid when energy is updated self._energy_grid = self._create_energy_grid() @property def upsample_factor(self) -> Numerical: - """Get the upsample factor.""" + """Get the upsample factor. + + Returns: + Numerical: The upsample factor. + """ return self._upsample_factor @upsample_factor.setter def upsample_factor(self, factor: Numerical) -> None: - """Set the upsample factor and recreate the dense grid.""" + """Set the upsample factor and recreate the dense grid. + + Args: + factor (Numerical): The new upsample factor. + + Raises: + TypeError: If factor is not a number or None. + ValueError: If factor is not greater than 1. + """ if factor is None: self._upsample_factor = factor self._energy_grid = self._create_energy_grid() @@ -137,6 +205,9 @@ def extension_factor(self) -> float: extended on both sides before convolution. 0.2 means extending by 20% of the original energy span on each side + + Returns: + float: The extension factor. """ return self._extension_factor @@ -151,12 +222,12 @@ def extension_factor(self, factor: Numerical) -> None: on each side. Args: - factor : float - The new extension factor. + factor (Numerical): The new extension factor. Raises: TypeError: If factor is not a number. """ + if not isinstance(factor, Numerical): raise TypeError('Extension factor must be a number.') if factor < 0.0: @@ -168,7 +239,12 @@ def extension_factor(self, factor: Numerical) -> None: @property def temperature(self) -> Optional[Parameter]: - """Get the temperature.""" + """Get the temperature. + + Returns: + Optional[Parameter]: The temperature parameter, or None if + detailed balance correction is disabled. + """ return self._temperature @@ -178,11 +254,12 @@ def temperature(self, temp: Parameter | float | None) -> None: If None, disables detailed balance correction and removes the temperature parameter. + Args: - temp : Parameter, float, or None - The temperature to set. The unit will be the same as - the existing temperature parameter if it exists, - otherwise 'K'. + temp (Parameter | float | None): The temperature to set. + The unit will be the same as the existing temperature + parameter if it exists, otherwise 'K'. + Raises: TypeError: If temp is not a float, Parameter, or None. """ @@ -206,7 +283,13 @@ def temperature(self, temp: Parameter | float | None) -> None: @property def normalize_detailed_balance(self) -> bool: - """Get whether to normalize the detailed balance factor.""" + """Get whether to normalize the detailed balance factor. + + If True, the detailed balance factor is divided by temperature. + + Returns: + bool: Whether to normalize the detailed balance factor. + """ return self._normalize_detailed_balance @@ -215,9 +298,11 @@ def normalize_detailed_balance(self, normalize: bool) -> None: """Set whether to normalize the detailed balance factor. If True, the detailed balance factor is divided by temperature. + Args: - normalize : bool - Whether to normalize the detailed balance factor. + normalize (bool): Whether to normalize the detailed balance + factor. + Raises: TypeError: If normalize is not a bool. """ @@ -236,24 +321,10 @@ def _create_energy_grid( If upsample_factor is None, no upsampling or extension is performed. This dense grid is used for convolution to improve accuracy. + Returns: - EnergyGrid - The dense grid created by upsampling and extending - energy. - The EnergyGrid has the following attributes: - energy_dense : np.ndarray - The upsampled and extended energy array. - energy_dense_centered : np.ndarray - The centered version of energy_dense - (used for resolution evaluation). - energy_dense_step : float - The spacing of energy_dense - (used for width checks and normalization). - energy_span_dense : float - The total span of energy_dense. (used for width checks). - energy_even_length_offset : float - The offset to apply if energy_dense has even length - (used for convolution alignment). + EnergyGrid: The dense grid created by upsampling and + extending energy. """ if self.upsample_factor is None: # Check if the array is uniformly spaced. @@ -326,19 +397,13 @@ def _check_width_thresholds( spacing. In both cases, the convolution accuracy may be compromised. + Args: - model : ComponentCollection or ModelComponent - The model to check. - model_name : str - A string indicating whether the model is a - 'sample model' or 'resolution model' for - warning messages. - returns: - None - warns: - UserWarning - If the component widths are not appropriate for the data - span or bin spacing. + model (ComponentCollection | ModelComponent): The model to + check + model_name (str): A string indicating whether the model is a + 'sample model' or 'resolution model' for warning + messages. """ # Handle ComponentCollection or ModelComponent @@ -369,6 +434,13 @@ def _check_width_thresholds( ) def __repr__(self) -> str: + """Return a string representation of the + NumericalConvolutionBase. + + Returns: + str: A string representation of the + NumericalConvolutionBase. + """ return ( f'{self.__class__.__name__}(' f'energy=array of shape {self.energy.values.shape},\n ' diff --git a/src/easydynamics/experiment/experiment.py b/src/easydynamics/experiment/experiment.py index 4245eba3..e506432b 100644 --- a/src/easydynamics/experiment/experiment.py +++ b/src/easydynamics/experiment/experiment.py @@ -38,6 +38,21 @@ def __init__( unique_name: str | None = None, data: sc.DataArray | str | None = None, ): + """Initialize the Experiment object. + + Args: + display_name (str): Display name of the experiment. + unique_name (str | None): Unique name of the experiment. If + None, a unique name will be generated. + data (sc.DataArray | str | None): Dataset associated with + the experiment. Can be a sc.DataArray or a filename + string to load from. If None, no data is loaded. + + Raises: + TypeError: If data is not a sc.DataArray, a string, or None. + ValueError: If the loaded data is missing required + coordinates. + """ super().__init__( display_name=display_name, unique_name=unique_name, @@ -123,7 +138,7 @@ def Q(self) -> sc.Variable | None: Returns: sc.Variable | None: The Q values from the dataset, or None - if no data is loaded. + if no data is loaded. """ if self._data is None: return None diff --git a/src/easydynamics/sample_model/background_model.py b/src/easydynamics/sample_model/background_model.py index 71a16881..c8b4f756 100644 --- a/src/easydynamics/sample_model/background_model.py +++ b/src/easydynamics/sample_model/background_model.py @@ -43,6 +43,21 @@ def __init__( components: ComponentCollection | ModelComponent | None = None, Q: Q_type | None = None, ): + """Initialize the BackgroundModel. + + Args: + display_name (str): Display name of the model. + unique_name (str | None): Unique name of the model. If None, + a unique name will be generated. + unit (str | sc.Unit | None): Unit of the model. Defaults to + "meV". + components (ModelComponent | ComponentCollection | None): + Template components of the model. If None, no components + are added. These components are copied into + ComponentCollections for each Q value. + Q (Q_type | None): Q values for the model. If None, Q is not + set. + """ super().__init__( display_name=display_name, unique_name=unique_name, diff --git a/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py b/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py index f85eb93b..7b12a1b0 100644 --- a/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py +++ b/src/easydynamics/sample_model/components/damped_harmonic_oscillator.py @@ -57,6 +57,26 @@ def __init__( display_name: str | None = 'DampedHarmonicOscillator', unique_name: str | None = None, ): + """Initialize the Damped Harmonic Oscillator. + + Args: + area (Int | float): Area under the curve. + center (Int | float): Resonance frequency, approximately the + peak position. + width (Int | float): Damping constant, approximately the + half width at half max (HWHM) of the peaks. + unit (str | sc.Unit): Unit of the parameters. + Defaults to "meV". + display_name (str | None): Display name of the component. + unique_name (str | None): Unique name of the component. + If None, a unique_name is automatically generated. + + Raises: + TypeError: If any of the parameters are not numbers or + Parameters. + ValueError: If center or width are not positive. + """ + super().__init__( display_name=display_name, unique_name=unique_name, @@ -90,7 +110,14 @@ def area(self) -> Parameter: @area.setter def area(self, value: Numeric) -> None: - """Set the value of the area parameter.""" + """Set the value of the area parameter. + + Args: + value (Numeric): The new value for the area parameter. + + Raises: + TypeError: If the value is not a number. + """ if not isinstance(value, Numeric): raise TypeError('area must be a number') self._area.value = value @@ -186,7 +213,7 @@ def __repr__(self) -> str: Returns: str: A string representation of the Damped Harmonic - Oscillator. + Oscillator. """ return ( f'DampedHarmonicOscillator(display_name = {self.display_name}, unit = {self._unit},\n \ diff --git a/src/easydynamics/sample_model/components/delta_function.py b/src/easydynamics/sample_model/components/delta_function.py index 6cc1faca..61741f71 100644 --- a/src/easydynamics/sample_model/components/delta_function.py +++ b/src/easydynamics/sample_model/components/delta_function.py @@ -49,6 +49,23 @@ def __init__( display_name: str | None = 'DeltaFunction', unique_name: str | None = None, ): + """Initialize the Delta function. + + Args: + center (Int | float | None): Center of the delta function. + If None, defaults to 0 and is fixed. + area (Int | float): Total area under the curve. + unit (str | sc.Unit): Unit of the parameters. + Defaults to "meV". + display_name (str | None): Name of the component. + unique_name (str | None): Unique name of the component. + If None, a unique_name is automatically generated. + + Raises: + TypeError: If center is not a number or None. + TypeError: If area is not a number. + TypeError: If unit is not a string or sc.Unit. + """ # Validate inputs and create Parameters if not given super().__init__( display_name=display_name, diff --git a/src/easydynamics/sample_model/components/gaussian.py b/src/easydynamics/sample_model/components/gaussian.py index d10d6978..7423714f 100644 --- a/src/easydynamics/sample_model/components/gaussian.py +++ b/src/easydynamics/sample_model/components/gaussian.py @@ -30,13 +30,13 @@ class Gaussian(CreateParametersMixin, ModelComponent): width. If the center is not provided, it will be centered at 0 and - fixed, which is typically what you want in QENS. + fixed, which is typically what you want in QENS. Args: - area (Int | float | Parameter): Area of the Gaussian. - center (Int | float | None | Parameter): Center of the + area (Int | float | Parameter | None): Area of the Gaussian. + center (Int | float | Parameter | None): Center of the Gaussian. If None, defaults to 0 and is fixed. - width (Int | float | Parameter): Standard deviation. + width (Int | float | Parameter | None): Standard deviation. unit (str | sc.Unit): Unit of the parameters. Defaults to "meV". display_name (str | None): Name of the component. @@ -61,6 +61,25 @@ def __init__( display_name: str | None = 'Gaussian', unique_name: str | None = None, ): + """Initialize the Gaussian component. + + Args: + area (Int | float | Parameter | None): Area of the Gaussian. + center (Int | float | Parameter | None): Center of the + Gaussian. If None, defaults to 0 and is fixed. + width (Int | float | Parameter | None): Standard deviation. + unit (str | sc.Unit): Unit of the parameters. Defaults to + "meV". + display_name (str | None): Name of the component. + unique_name (str | None): Unique name of the component. if + None, a unique_name is automatically generated. + + Raises: + TypeError: If area, center, or width are not numbers or + Parameters. + ValueError: If width is not positive. + TypeError: If unit is not a string or sc.Unit. + """ # Validate inputs and create Parameters if not given super().__init__( display_name=display_name, diff --git a/src/easydynamics/sample_model/components/lorentzian.py b/src/easydynamics/sample_model/components/lorentzian.py index 28685f98..b8da443e 100644 --- a/src/easydynamics/sample_model/components/lorentzian.py +++ b/src/easydynamics/sample_model/components/lorentzian.py @@ -56,6 +56,25 @@ def __init__( display_name: str | None = 'Lorentzian', unique_name: str | None = None, ): + """Initialize the Lorentzian component. + + Args: + area (Int | float | Parameter): Area of the Lorentzian. + center (Int | float | None | Parameter): Center of the + Lorentzian. If None, defaults to 0 and is fixed + width (Int | float | Parameter): Half width at half maximum + (HWHM). + unit (str | sc.Unit): Unit of the parameters. Defaults to + "meV". + display_name (str | None): Name of the component. + unique_name (str | None): Unique name of the component. If + None, a unique_name is automatically generated. + + Raises: + TypeError: If any of the parameters are of the wrong type. + ValueError: If width is not positive. + """ + super().__init__( display_name=display_name, unit=unit, @@ -183,7 +202,7 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray) return self.area.value * normalization / denominator - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the Lorentzian. Returns: diff --git a/src/easydynamics/sample_model/components/model_component.py b/src/easydynamics/sample_model/components/model_component.py index 470e2cb2..09ed6514 100644 --- a/src/easydynamics/sample_model/components/model_component.py +++ b/src/easydynamics/sample_model/components/model_component.py @@ -40,6 +40,19 @@ def __init__( display_name: str | None = None, unique_name: str | None = None, ): + """Initialize the ModelComponent. + + Args: + unit (str | sc.Unit): The unit of the model component. + Default is 'meV'. + display_name (str | None): A human-readable name for the + component. Default is None. + unique_name (str | None): A unique identifier for the + component. Default is None. + + Raises: + TypeError: If unit is not a string or scipp Unit. + """ self.validate_unit(unit) super().__init__(display_name=display_name, unique_name=unique_name) self._unit = unit @@ -201,14 +214,14 @@ def evaluate( Args: x (Numeric | list[Numeric] | np.ndarray | sc.Variable | - sc.DataArray): Input values. + sc.DataArray): Input values. Returns: np.ndarray: Evaluated function values. """ pass - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the ModelComponent. Returns: diff --git a/src/easydynamics/sample_model/components/polynomial.py b/src/easydynamics/sample_model/components/polynomial.py index fa475b2c..9210c484 100644 --- a/src/easydynamics/sample_model/components/polynomial.py +++ b/src/easydynamics/sample_model/components/polynomial.py @@ -49,6 +49,25 @@ def __init__( display_name: str | None = 'Polynomial', unique_name: str | None = None, ): + """Initialize the Polynomial component. + + Args: + coefficients (list or tuple): Coefficients c0, c1, ..., cN + unit (str or sc.Unit): Unit of the Polynomial component. + display_name (str): Display name of the Polynomial + component. + unique_name (str or None): Unique name of the component. + If None, a unique_name is automatically generated. + + Raises: + TypeError: If coefficients is not a sequence of numbers or + Parameters. + ValueError: If coefficients is an empty sequence. + TypeError: If any item in coefficients is not a number or + Parameter. + UnitError: If unit is not a string or sc.Unit. + """ + super().__init__(display_name=display_name, unit=unit, unique_name=unique_name) if not isinstance(coefficients, (list, tuple, np.ndarray)): diff --git a/src/easydynamics/sample_model/components/voigt.py b/src/easydynamics/sample_model/components/voigt.py index dc0c3315..117b5652 100644 --- a/src/easydynamics/sample_model/components/voigt.py +++ b/src/easydynamics/sample_model/components/voigt.py @@ -55,6 +55,28 @@ def __init__( display_name: str | None = 'Voigt', unique_name: str | None = None, ): + """Initialize a Voigt component. + + Args: + area (Int | float): Total area under the curve. + center (Int | float | None): Center of the Voigt profile. + gaussian_width (Int | float): Standard deviation of the + Gaussian part. + lorentzian_width (Int | float): Half width at half max + (HWHM) of the Lorentzian part. + unit (str | sc.Unit): Unit of the parameters. Defaults to + "meV" + display_name (str | None): Display name of the component. + unique_name (str | None): Unique name of the component. + If None, a unique_name is automatically generated. + + Raises: + TypeError: If any of the parameters are not of the correct + type. + ValueError: If any of the parameters are not valid (e.g. + negative widths). + """ + super().__init__( display_name=display_name, unit=unit, @@ -199,9 +221,9 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray) Args: - x (Numeric or list or np.ndarray or sc.Variable or - sc.DataArray): - The x values at which to evaluate the Voigt. + x (Numeric | list[Numeric] | np.ndarray | sc.Variable | + sc.DataArray): The x values at which to evaluate the + Voigt. Returns: np.ndarray: The intensity of the Voigt at the given x @@ -216,7 +238,7 @@ def evaluate(self, x: Numeric | list | np.ndarray | sc.Variable | sc.DataArray) self.lorentzian_width.value, ) - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the Voigt. Returns: diff --git a/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py b/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py index 1ecb8c2a..2198e032 100644 --- a/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py +++ b/src/easydynamics/sample_model/diffusion_model/brownian_translational_diffusion.py @@ -205,7 +205,7 @@ def create_component_collections( Args: Q (Number, list, or np.ndarray): Scattering vector values. component_display_name (str): Name of the Lorentzian - component. + component. Returns: List[ComponentCollection]: List of ComponentCollections with @@ -330,13 +330,13 @@ def _write_area_dependency_map_expression(self) -> Dict[str, DescriptorNumber]: # dunder methods # ------------------------------------------------------------------ - def __repr__(self): + def __repr__(self) -> str: """String representation of the BrownianTranslationalDiffusion model. Returns: str: String representation of the - BrownianTranslationalDiffusion model. + BrownianTranslationalDiffusion model. """ return ( f'BrownianTranslationalDiffusion(display_name={self.display_name},' diff --git a/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py b/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py index 096272ee..603dced8 100644 --- a/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py +++ b/src/easydynamics/sample_model/diffusion_model/diffusion_model_base.py @@ -131,7 +131,7 @@ def scale(self, scale: Numeric) -> None: # dunder methods # ------------------------------------------------------------------ - def __repr__(self): + def __repr__(self) -> str: """String representation of the Diffusion model. Returns: diff --git a/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py b/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py index b7e28573..3fa8959d 100644 --- a/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py +++ b/src/easydynamics/sample_model/diffusion_model/jump_translational_diffusion.py @@ -73,23 +73,24 @@ def __init__( """Initialize a new JumpTranslationalDiffusion model. Args: - display_name (str): Display name of the diffusion model. - unique_name (str | None): Unique name of the diffusion model. If - None, a unique name will be generated. - unit (str | sc.Unit): Unit of the diffusion model. Must be - convertible to meV. Defaults to "meV". - scale (Numeric): Scale factor for the diffusion model. Must be - a non-negative number. Defaults to 1.0. - diffusion_coefficient (Numeric): Diffusion coefficient D in - m^2/s. Defaults to 1.0. - relaxation_time (Numeric): Relaxation time t in ps. Defaults to - 1.0. + display_name (str): Display name of the diffusion model. + unique_name (str | None): Unique name of the diffusion + model. If + None, a unique name will be generated. + unit (str | sc.Unit): Unit of the diffusion model. Must be + convertible to meV. Defaults to "meV". + scale (Numeric): Scale factor for the diffusion model. Must + be a non-negative number. Defaults to 1.0. + diffusion_coefficient (Numeric): Diffusion coefficient D in + m^2/s. Defaults to 1.0. + relaxation_time (Numeric): Relaxation time t in ps. Defaults + to 1.0. Raises: - TypeError: If scale, diffusion_coefficient, or relaxation_time - are not numbers. - ValueError: If scale is negative. - UnitError: If unit is not a string or scipp Unit + TypeError: If scale, diffusion_coefficient, or + relaxation_time are not numbers. + ValueError: If scale is negative. + UnitError: If unit is not a valid unit string or scipp Unit. """ super().__init__( display_name=display_name, @@ -376,7 +377,7 @@ def _write_area_dependency_map_expression(self) -> Dict[str, DescriptorNumber]: # dunder methods ################################ - def __repr__(self): + def __repr__(self) -> str: """String representation of the JumpTranslationalDiffusion model. diff --git a/src/easydynamics/sample_model/instrument_model.py b/src/easydynamics/sample_model/instrument_model.py index 732955fc..aadd543f 100644 --- a/src/easydynamics/sample_model/instrument_model.py +++ b/src/easydynamics/sample_model/instrument_model.py @@ -64,6 +64,37 @@ def __init__( energy_offset: Numeric | None = None, unit: str | sc.Unit = 'meV', ): + """Initialize an InstrumentModel. + + Args: + display_name (str | None): The display name of the + InstrumentModel. Default is "MyInstrumentModel". + unique_name (str | None): The unique name of the + InstrumentModel. Default is None. + Q (np.ndarray | list | sc.Variable | None): The Q values + where the instrument is modelled. + resolution_model (ResolutionModel | None): The resolution + model of the instrument. If None, an empty resolution + model is created and no resolution convolution is + carried out. Default is None. + background_model (BackgroundModel | None): The background + model of the instrument. If None, an empty background + model is created, and the background evaluates to 0. + Default is None. + energy_offset (float | int | None): Template energy offset + of the instrument. Will be copied to each Q value. If + None, the energy offset will be 0. Default is None. + unit (str | sc.Unit): The unit of the energy axis. Default + is 'meV'. + + Raises: + TypeError: If resolution_model is not a ResolutionModel or + None + TypeError: If background_model is not a BackgroundModel or + None + TypeError: If energy_offset is not a number or None + UnitError: If unit is not a valid unit string or scipp Unit. + """ super().__init__( display_name=display_name, unique_name=unique_name, @@ -379,7 +410,7 @@ def _on_background_model_change(self) -> None: # Dunder methods # ------------------------------------------------------------- - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the InstrumentModel. Returns: diff --git a/src/easydynamics/sample_model/model_base.py b/src/easydynamics/sample_model/model_base.py index 18098cd0..cfd2cb89 100644 --- a/src/easydynamics/sample_model/model_base.py +++ b/src/easydynamics/sample_model/model_base.py @@ -32,15 +32,14 @@ class ModelBase(EasyScienceModelBase): Template components of the model. If None, no components are added. These components are copied into ComponentCollections for each Q value. - Q (Q_type | None): Q values for the model. If None, Q is not - set. + Q (ArrayLike | sc.Variable | None): Q values for the model. If + None, Q is not set. Attributes: unit (str | sc.Unit): Unit of the model. components (list[ModelComponent]): List of ModelComponents in the model. - Q (np.ndarray | Numeric | list | ArrayLike | sc.Variable - | None): Q values of the model. + Q (ArrayLike | sc.Variable | None): Q values of the model. """ def __init__( @@ -51,6 +50,21 @@ def __init__( components: ModelComponent | ComponentCollection | None = None, Q: Q_type | None = None, ): + """Initialize the ModelBase. + + Args: + display_name (str): Display name of the model. + unique_name (str | None): Unique name of the model. If None, + a unique name will be generated. + unit (str | sc.Unit | None): Unit of the model. Defaults to + "meV". + components (ModelComponent | ComponentCollection | None): + Template components of the model. If None, no components + are added. These components are copied into + ComponentCollections for each Q value. + Q (ArrayLike | sc.Variable | None): Q values for the model. + If None, Q is not set. + """ super().__init__( display_name=display_name, unique_name=unique_name, @@ -111,8 +125,8 @@ def append_component(self, component: ModelComponent | ComponentCollection) -> N SampleModel. Args: - component (ModelComponent | ComponentCollection): - The ModelComponent or ComponentCollection to append. + component (ModelComponent | ComponentCollection): The + ModelComponent or ComponentCollection to append. """ self._components.append_component(component) self._on_components_change() @@ -123,7 +137,7 @@ def remove_component(self, unique_name: str) -> None: Args: unique_name (str): The unique name of the ModelComponent - to remove. + to remove. """ self._components.remove_component(unique_name) self._on_components_change() @@ -350,7 +364,7 @@ def _on_components_change(self) -> None: # dunder methods # ------------------------------------------------------------------ - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the ModelBase. Returns: diff --git a/src/easydynamics/sample_model/resolution_model.py b/src/easydynamics/sample_model/resolution_model.py index ae042b0c..d4d23e39 100644 --- a/src/easydynamics/sample_model/resolution_model.py +++ b/src/easydynamics/sample_model/resolution_model.py @@ -45,6 +45,27 @@ def __init__( components: ComponentCollection | ModelComponent | None = None, Q: Q_type | None = None, ): + """Initialize a ResolutionModel. + + Args: + display_name (str): Display name of the model. + unique_name (str | None): Unique name of the model. If None, + a unique name will be generated. + unit (str | sc.Unit | None): Unit of the model. Defaults to + "meV". + components (ModelComponent | ComponentCollection | None): + Template components of the model. If None, no components + are added. These components are copied into + ComponentCollections for each Q value. + Q (Q_type | None): Q values for the model. If None, Q is not + set. + + Raises: + TypeError: If components is not a ModelComponent or + ComponentCollection. + ValueError: If Q is not a valid Q_type. + """ + super().__init__( display_name=display_name, unique_name=unique_name, @@ -53,7 +74,7 @@ def __init__( Q=Q, ) - def append_component(self, component: ModelComponent | ComponentCollection): + def append_component(self, component: ModelComponent | ComponentCollection) -> None: """Append a component to the ResolutionModel. Does not allow DeltaFunction or Polynomial components, as these @@ -61,7 +82,7 @@ def append_component(self, component: ModelComponent | ComponentCollection): Args: component (ModelComponent | ComponentCollection): - Component(s) to append. + Component(s) to append. Raises: TypeError: If the component is a DeltaFunction or Polynomial diff --git a/src/easydynamics/sample_model/sample_model.py b/src/easydynamics/sample_model/sample_model.py index ce94bbe5..ef5cb9ab 100644 --- a/src/easydynamics/sample_model/sample_model.py +++ b/src/easydynamics/sample_model/sample_model.py @@ -44,6 +44,19 @@ class SampleModel(ModelBase): Defaults to "K". divide_by_temperature (bool): Whether to divide the detailed balance factor by temperature. Defaults to True. + + Attributes: + unit (str | sc.Unit): Unit of the model. + components (list[ModelComponent]): List of ModelComponents in + the model. + Q (np.ndarray | Numeric | list | ArrayLike | sc.Variable + | None): Q values of the model. + diffusion_models (list[DiffusionModelBase]): List of diffusion + models in the SampleModel. + temperature (Parameter | None): Temperature Parameter for + detailed balancing, or None if not set. + divide_by_temperature (bool): Whether to divide the detailed + balance factor by temperature. """ def __init__( @@ -58,6 +71,38 @@ def __init__( temperature_unit: str | sc.Unit = 'K', divide_by_temperature: bool = True, ): + """Initialize the SampleModel. + + Args: + display_name (str): Display name of the model. + unique_name (str | None): Unique name of the model. If None, + a unique name will be generated. + unit (str | sc.Unit | None): Unit of the model. If None, + defaults to "meV". + components (ModelComponent | ComponentCollection | None): + Template components of the model. If None, no components + are added. These components are copied into + ComponentCollections for each Q value. + Q (Number, list, np.ndarray, sc.array | None): + Q values for the model. If None, Q is not set. + diffusion_models (DiffusionModelBase | + list[DiffusionModelBase] | None): Diffusion models to + include in the SampleModel. If None, no diffusion models + are added. + temperature (float | None): Temperature for detailed + balancing. If None, no detailed balancing is applied. + temperature_unit (str | sc.Unit): Unit of the temperature. + Defaults to "K". + divide_by_temperature (bool): Whether to divide the detailed + balance factor by temperature. Defaults to True. + + Raises: + TypeError: If diffusion_models is not a DiffusionModelBase, + a list of DiffusionModelBase, or None. + TypeError: If temperature is not a number or None. + ValueError: If temperature is negative. + TypeError: If divide_by_temperature is not a bool. + """ if diffusion_models is None: self._diffusion_models = [] elif isinstance(diffusion_models, DiffusionModelBase): @@ -110,7 +155,7 @@ def append_diffusion_model(self, diffusion_model: DiffusionModelBase) -> None: Args: diffusion_model (DiffusionModelBase): The DiffusionModel - to append. + to append. Raises: TypeError: If the diffusion_model is not a @@ -133,7 +178,7 @@ def remove_diffusion_model(self, name: 'str') -> None: Raises: ValueError: If no DiffusionModel with the given unique name - is found. + is found. """ for i, dm in enumerate(self._diffusion_models): if dm.unique_name == name: @@ -395,7 +440,7 @@ def _on_diffusion_models_change(self) -> None: # dunder methods # ------------------------------------------------------------------ - def __repr__(self): + def __repr__(self) -> str: """Return a string representation of the SampleModel. Returns: diff --git a/src/easydynamics/utils/detailed_balance.py b/src/easydynamics/utils/detailed_balance.py index 8afcd47c..0790412b 100644 --- a/src/easydynamics/utils/detailed_balance.py +++ b/src/easydynamics/utils/detailed_balance.py @@ -29,13 +29,16 @@ def _detailed_balance_factor( temperature_unit: str | sc.Unit = 'K', divide_by_temperature: bool = True, ) -> np.ndarray: - """ - Compute the detailed balance factor (DBF): $DBF(E, T) = E*(n(E)+1)=E - / (1 - exp(-E / (kB*T)))$, where $n(E)$ is the Bose-Einstein - distribution, $E$ is the energy transfer, and $T$ is the - temperature. $k_B$ is the Boltzmann constant. If - divide_by_temperature is True, the result is normalized by kB*T to - have value 1 at E=0. + r""" + Compute the detailed balance factor (DBF): + $$ + DBF(E, T) = E(n(E)+1)=\frac{E}{(1 - e^{-E / (k_B*T)})}}, + $$ + where $n(E)$ is the Bose-Einstein distribution, $E$ is the energy + transfer, and $T$ is the temperature. $k_B$ is the Boltzmann + constant. + If divide_by_temperature is True, the result is normalized by + $k_B*T$ to have value 1 at $E=0$. Args: energy (number | list | np.ndarray | scipp.Variable): The energy diff --git a/src/easydynamics/utils/utils.py b/src/easydynamics/utils/utils.py index e3cc842d..0ac12ab6 100644 --- a/src/easydynamics/utils/utils.py +++ b/src/easydynamics/utils/utils.py @@ -8,20 +8,18 @@ Numeric = float | int Q_type = np.ndarray | Numeric | list | ArrayLike | sc.Variable +energy_type = np.ndarray | Numeric | list | ArrayLike | sc.Variable def _validate_and_convert_Q(Q: Q_type | None) -> np.ndarray | None: """Validate and convert Q to a numpy array. - Parameters - ---------- - Q : Number, list, np.ndarray or sc.Variable - Scattering vector values in 1/angstrom. - Returns - ------- - np.ndarray - Q as a np.ndarray. - TODO: Update to sc.array, also propagate that to diffusionmodel + Args: + Q (Number, list, np.ndarray or sc.Variable): Scattering vector + values in 1/angstrom. + + Returns: + np.ndarray: Q as a np.ndarray. """ if Q is None: return None @@ -48,19 +46,14 @@ def _validate_and_convert_Q(Q: Q_type | None) -> np.ndarray | None: def _validate_unit(unit: str | sc.Unit | None) -> sc.Unit | None: """Validate that the unit is a string or scipp Unit. - Parameters - ---------- - unit : str or sc.Unit or None - Unit to validate. - Returns - ------- - sc.Unit | None - Validated unit or None. - - Raises - ------ - TypeError - If unit is not None, a string, or a scipp Unit. + Args: + unit (str | sc.Unit | None): Unit to validate. + + Returns: + sc.Unit | None: Validated unit or None. + + Raises: + TypeError: If unit is not None, a string, or a scipp Unit. """ if unit is not None and not isinstance(unit, (str, sc.Unit)): diff --git a/tests/unit/easydynamics/analysis/test_analysis_base.py b/tests/unit/easydynamics/analysis/test_analysis_base.py index f4e937ad..b2dabf00 100644 --- a/tests/unit/easydynamics/analysis/test_analysis_base.py +++ b/tests/unit/easydynamics/analysis/test_analysis_base.py @@ -261,7 +261,7 @@ def test_extra_parameters_property(self, analysis_base, extra_parameters): def test_extra_parameters_setter_invalid_type(self, analysis_base, invalid_extra_parameters): with pytest.raises( TypeError, - match='extra_parameters must be a Parameter or a list of Parameters.', + match='extra_parameters must be', ): analysis_base.extra_parameters = invalid_extra_parameters