niess 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. niess-0.0.1/.github/workflows/build-and-publish.yml +43 -0
  2. niess-0.0.1/.gitignore +171 -0
  3. niess-0.0.1/.idea/.gitignore +8 -0
  4. niess-0.0.1/.idea/inspectionProfiles/Project_Default.xml +58 -0
  5. niess-0.0.1/.idea/inspectionProfiles/profiles_settings.xml +6 -0
  6. niess-0.0.1/.idea/misc.xml +7 -0
  7. niess-0.0.1/.idea/modules.xml +8 -0
  8. niess-0.0.1/.idea/niess.iml +10 -0
  9. niess-0.0.1/.idea/vcs.xml +6 -0
  10. niess-0.0.1/LICENSE +28 -0
  11. niess-0.0.1/LICENSE.txt +9 -0
  12. niess-0.0.1/PKG-INFO +47 -0
  13. niess-0.0.1/README.md +21 -0
  14. niess-0.0.1/pyproject.toml +70 -0
  15. niess-0.0.1/src/niess/__about__.py +4 -0
  16. niess-0.0.1/src/niess/__init__.py +24 -0
  17. niess-0.0.1/src/niess/bifrost/__init__.py +15 -0
  18. niess-0.0.1/src/niess/bifrost/analyzer.py +116 -0
  19. niess-0.0.1/src/niess/bifrost/arm.py +142 -0
  20. niess-0.0.1/src/niess/bifrost/bifrost.py +19 -0
  21. niess-0.0.1/src/niess/bifrost/channel.py +160 -0
  22. niess-0.0.1/src/niess/bifrost/combine.py +18 -0
  23. niess-0.0.1/src/niess/bifrost/parameters.py +62 -0
  24. niess-0.0.1/src/niess/bifrost/rowland.py +153 -0
  25. niess-0.0.1/src/niess/bifrost/tank.py +117 -0
  26. niess-0.0.1/src/niess/bifrost/triplet.py +147 -0
  27. niess-0.0.1/src/niess/components/__init__.py +14 -0
  28. niess-0.0.1/src/niess/components/crystals.py +156 -0
  29. niess-0.0.1/src/niess/components/detectors.py +204 -0
  30. niess-0.0.1/src/niess/components/secondary.py +331 -0
  31. niess-0.0.1/src/niess/cspec/__init__.py +7 -0
  32. niess-0.0.1/src/niess/cspec/cspec.py +0 -0
  33. niess-0.0.1/src/niess/cspec/pack.py +107 -0
  34. niess-0.0.1/src/niess/cspec/parameters.py +39 -0
  35. niess-0.0.1/src/niess/cspec/tank.py +74 -0
  36. niess-0.0.1/src/niess/mccode.py +13 -0
  37. niess-0.0.1/src/niess/spatial.py +196 -0
  38. niess-0.0.1/src/niess/utilities.py +25 -0
  39. niess-0.0.1/tests/__init__.py +3 -0
  40. niess-0.0.1/tests/test_bifrost_tank.py +90 -0
  41. niess-0.0.1/tests/test_crystal.py +109 -0
@@ -0,0 +1,43 @@
1
+ name: Choppera Python Package
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ branches: ["main"]
8
+ release:
9
+ types:
10
+ - published
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: |
24
+ 3.10
25
+ 3.11
26
+ 3.12
27
+ 3.13
28
+ - name: Set up pip cache
29
+ if: runner.os == 'Linux'
30
+ uses: actions/cache@v4
31
+ with:
32
+ path: ~/.cache/pip
33
+ key: "${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }}"
34
+ restore-keys: ${{ runner.os }}-pip-
35
+ - name: Install Hatch
36
+ run: pipx install hatch
37
+ - name: Run tests
38
+ run: hatch test
39
+ - name: Build dist
40
+ run: hatch build
41
+ - name: Publish artifacts to PyPI
42
+ if: ${{ github.event.action == 'published' }}
43
+ uses: pypa/gh-action-pypi-publish@release/v1
niess-0.0.1/.gitignore ADDED
@@ -0,0 +1,171 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
116
+ .pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
121
+ __pypackages__/
122
+
123
+ # Celery stuff
124
+ celerybeat-schedule
125
+ celerybeat.pid
126
+
127
+ # SageMath parsed files
128
+ *.sage.py
129
+
130
+ # Environments
131
+ .env
132
+ .venv
133
+ env/
134
+ venv/
135
+ ENV/
136
+ env.bak/
137
+ venv.bak/
138
+
139
+ # Spyder project settings
140
+ .spyderproject
141
+ .spyproject
142
+
143
+ # Rope project settings
144
+ .ropeproject
145
+
146
+ # mkdocs documentation
147
+ /site
148
+
149
+ # mypy
150
+ .mypy_cache/
151
+ .dmypy.json
152
+ dmypy.json
153
+
154
+ # Pyre type checker
155
+ .pyre/
156
+
157
+ # pytype static type analyzer
158
+ .pytype/
159
+
160
+ # Cython debug symbols
161
+ cython_debug/
162
+
163
+ # PyCharm
164
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
165
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
167
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
169
+
170
+ # PyPI configuration file
171
+ .pypirc
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,58 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
5
+ <option name="ourVersions">
6
+ <value>
7
+ <list size="5">
8
+ <item index="0" class="java.lang.String" itemvalue="3.13" />
9
+ <item index="1" class="java.lang.String" itemvalue="3.10" />
10
+ <item index="2" class="java.lang.String" itemvalue="3.11" />
11
+ <item index="3" class="java.lang.String" itemvalue="3.12" />
12
+ <item index="4" class="java.lang.String" itemvalue="3.9" />
13
+ </list>
14
+ </value>
15
+ </option>
16
+ </inspection_tool>
17
+ <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
18
+ <option name="ignoredPackages">
19
+ <value>
20
+ <list size="18">
21
+ <item index="0" class="java.lang.String" itemvalue="ess-streaming-data-types" />
22
+ <item index="1" class="java.lang.String" itemvalue="jupyterlab-fasta" />
23
+ <item index="2" class="java.lang.String" itemvalue="ipyevents" />
24
+ <item index="3" class="java.lang.String" itemvalue="jupyterlab-night" />
25
+ <item index="4" class="java.lang.String" itemvalue="jupyterlite-pyodide-kernel" />
26
+ <item index="5" class="java.lang.String" itemvalue="jupyterlite-p5-kernel" />
27
+ <item index="6" class="java.lang.String" itemvalue="plotly" />
28
+ <item index="7" class="java.lang.String" itemvalue="ipycanvas" />
29
+ <item index="8" class="java.lang.String" itemvalue="jupyterlab-language-pack-zh-CN" />
30
+ <item index="9" class="java.lang.String" itemvalue="jupyterlite-core" />
31
+ <item index="10" class="java.lang.String" itemvalue="jupyterlab-geojson" />
32
+ <item index="11" class="java.lang.String" itemvalue="jupyterlab_miami_nights" />
33
+ <item index="12" class="java.lang.String" itemvalue="ipyleaflet" />
34
+ <item index="13" class="java.lang.String" itemvalue="bqplot" />
35
+ <item index="14" class="java.lang.String" itemvalue="ipympl" />
36
+ <item index="15" class="java.lang.String" itemvalue="jupyterlab-language-pack-fr-FR" />
37
+ <item index="16" class="java.lang.String" itemvalue="jupyterlite-javascript-kernel" />
38
+ <item index="17" class="java.lang.String" itemvalue="notebook" />
39
+ </list>
40
+ </value>
41
+ </option>
42
+ </inspection_tool>
43
+ <inspection_tool class="PyPep8Inspection" enabled="true" level="INFORMATION" enabled_by_default="true">
44
+ <option name="ignoredErrors">
45
+ <list>
46
+ <option value="E301" />
47
+ </list>
48
+ </option>
49
+ </inspection_tool>
50
+ <inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
51
+ <option name="ignoredErrors">
52
+ <list>
53
+ <option value="N802" />
54
+ </list>
55
+ </option>
56
+ </inspection_tool>
57
+ </profile>
58
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="Python 3.9" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 virtualenv at ~/PycharmProjects/niess/.venv" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/niess.iml" filepath="$PROJECT_DIR$/.idea/niess.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
6
+ </content>
7
+ <orderEntry type="jdk" jdkName="Python 3.13 virtualenv at ~/PycharmProjects/niess/.venv" jdkType="Python SDK" />
8
+ <orderEntry type="sourceFolder" forTests="false" />
9
+ </component>
10
+ </module>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
niess-0.0.1/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Gregory S. Tucker
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Gregory Tucker <gregory.tucker@ess.eu>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
niess-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: niess
3
+ Version: 0.0.1
4
+ Project-URL: Documentation, https://github.com/g5t/niess#readme
5
+ Project-URL: Issues, https://github.com/g5t/niess/issues
6
+ Project-URL: Source, https://github.com/g5t/niess
7
+ Author-email: Gregory Tucker <gregory.tucker@ess.eu>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ License-File: LICENSE.txt
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: Implementation :: CPython
19
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
20
+ Requires-Python: >=3.8
21
+ Requires-Dist: mccode-antlr>=0.9.3
22
+ Requires-Dist: numpy
23
+ Requires-Dist: scipp>=25.1.0
24
+ Requires-Dist: scipy
25
+ Description-Content-Type: text/markdown
26
+
27
+ # niess
28
+
29
+ [![PyPI - Version](https://img.shields.io/pypi/v/niess.svg)](https://pypi.org/project/niess)
30
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/niess.svg)](https://pypi.org/project/niess)
31
+
32
+ -----
33
+
34
+ ## Table of Contents
35
+
36
+ - [Installation](#installation)
37
+ - [License](#license)
38
+
39
+ ## Installation
40
+
41
+ ```console
42
+ pip install niess
43
+ ```
44
+
45
+ ## License
46
+
47
+ `niess` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
niess-0.0.1/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # niess
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/niess.svg)](https://pypi.org/project/niess)
4
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/niess.svg)](https://pypi.org/project/niess)
5
+
6
+ -----
7
+
8
+ ## Table of Contents
9
+
10
+ - [Installation](#installation)
11
+ - [License](#license)
12
+
13
+ ## Installation
14
+
15
+ ```console
16
+ pip install niess
17
+ ```
18
+
19
+ ## License
20
+
21
+ `niess` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
@@ -0,0 +1,70 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "niess"
7
+ dynamic = ["version"]
8
+ description = ''
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = "MIT"
12
+ keywords = []
13
+ authors = [
14
+ { name = "Gregory Tucker", email = "gregory.tucker@ess.eu" },
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Programming Language :: Python",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: Implementation :: CPython",
25
+ "Programming Language :: Python :: Implementation :: PyPy",
26
+ ]
27
+ dependencies = [
28
+ "scipp>=25.1.0",
29
+ "numpy",
30
+ "scipy",
31
+ "mccode-antlr>=0.9.3",
32
+ ]
33
+
34
+ [project.urls]
35
+ Documentation = "https://github.com/g5t/niess#readme"
36
+ Issues = "https://github.com/g5t/niess/issues"
37
+ Source = "https://github.com/g5t/niess"
38
+
39
+ [tool.hatch.version]
40
+ path = "src/niess/__about__.py"
41
+
42
+ [tool.hatch.envs.default]
43
+ type = "virtual"
44
+ path = ".venv"
45
+
46
+ [tool.hatch.envs.types]
47
+ extra-dependencies = [
48
+ "mypy>=1.0.0",
49
+ ]
50
+ [tool.hatch.envs.types.scripts]
51
+ check = "mypy --install-types --non-interactive {args:src/niess tests}"
52
+
53
+ [tool.coverage.run]
54
+ source_pkgs = ["niess", "tests"]
55
+ branch = true
56
+ parallel = true
57
+ omit = [
58
+ "src/niess/__about__.py",
59
+ ]
60
+
61
+ [tool.coverage.paths]
62
+ niess = ["src/niess", "*/niess/src/niess"]
63
+ tests = ["tests", "*/niess/tests"]
64
+
65
+ [tool.coverage.report]
66
+ exclude_lines = [
67
+ "no cov",
68
+ "if __name__ == .__main__.:",
69
+ "if TYPE_CHECKING:",
70
+ ]
@@ -0,0 +1,4 @@
1
+ # SPDX-FileCopyrightText: 2025-present Gregory Tucker <gregory.tucker@ess.eu>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ __version__ = "0.0.1"
@@ -0,0 +1,24 @@
1
+ # SPDX-FileCopyrightText: 2025-present Gregory Tucker <gregory.tucker@ess.eu>
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ from .components import (
5
+ DirectSecondary,
6
+ IndirectSecondary,
7
+ IdealCrystal,
8
+ Crystal,
9
+ Wire,
10
+ DiscreteWire,
11
+ DiscreteTube,
12
+ He3Tube
13
+ )
14
+
15
+ __all__ = [
16
+ DirectSecondary,
17
+ IndirectSecondary,
18
+ IdealCrystal,
19
+ Crystal,
20
+ Wire,
21
+ DiscreteWire,
22
+ DiscreteTube,
23
+ He3Tube
24
+ ]
@@ -0,0 +1,15 @@
1
+ from .arm import Arm
2
+ from .tank import Tank
3
+ from .bifrost import BIFROST
4
+ from .channel import Channel
5
+ from .triplet import Triplet
6
+ from .analyzer import Analyzer
7
+
8
+ __all__ = [
9
+ Arm,
10
+ Tank,
11
+ BIFROST,
12
+ Channel,
13
+ Triplet,
14
+ Analyzer
15
+ ]
@@ -0,0 +1,116 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class Analyzer:
6
+ from mccode_antlr.assembler import Assembler
7
+ from ..components import Crystal
8
+ from scipp import Variable
9
+
10
+ blades: tuple[Crystal, ...] # 7-9 blades
11
+
12
+ @property
13
+ def central_blade(self):
14
+ return self.blades[len(self.blades) >> 1]
15
+
16
+ @property
17
+ def count(self):
18
+ return len(self.blades)
19
+
20
+ @staticmethod
21
+ def from_calibration(position: Variable, focus: Variable, tau: Variable, **params):
22
+ from scipp import scalar, vector
23
+ from scipp.spatial import rotation
24
+ from ..spatial import is_scipp_vector
25
+ from .rowland import rowland_blades
26
+ from ..components import Crystal
27
+ map(lambda x: is_scipp_vector(*x), ((position, 'position'), (focus, 'focus'), (tau, 'tau')))
28
+ count = params.get('blade_count', scalar(9)) # most analyzers have 9 blades
29
+ shape = params.get('shape', vector([10., 200., 2.], unit='mm'))
30
+ orient = params.get('orient', None)
31
+ orient = rotation(value=[0, 0, 0, 1.]) if orient is None else orient
32
+ mosaic = params.get('mosaic', scalar(40., unit='arcminutes'))
33
+ # qin_coverage = params.get('qin_coverage', params.get('coverage', scalar(0.1, unit='1/angstrom')))
34
+ coverage = params.get('coverage', scalar(2.0, unit='degree'))
35
+ source = params.get('source', params.get('sample_position', vector([0, 0, 0], unit='m')))
36
+ gap = params.get('gap', None)
37
+ #
38
+ # Use the Rowland geometry to define each blade position & normal direction
39
+ positions, taus = rowland_blades(source, position, focus, coverage, shape.fields.x, count.value, tau, gap)
40
+
41
+ blades = [Crystal(p, t, shape, orient, mosaic) for p, t in zip(positions, taus)]
42
+ return Analyzer(tuple(blades))
43
+
44
+ def triangulate(self, unit=None):
45
+ from ..spatial import combine_triangulations
46
+ vts = [blade.triangulate(unit=unit) for blade in self.blades]
47
+ return combine_triangulations(vts)
48
+
49
+ def bounding_box(self, basis: Variable, unit=None):
50
+ from scipp import concat
51
+ from ..spatial import combine_bounding_boxes
52
+ boxes = concat(tuple(b.bounding_box(basis, unit) for b in self.blades), dim='blades')
53
+ return combine_bounding_boxes(boxes)
54
+
55
+ def coverage(self, sample: Variable, unit=None):
56
+ from scipp import norm, dot, cross, max, min, atan2, vector, concat
57
+ unit = unit or 'radian'
58
+ # Define a pseudo McStas coordinate system (requiring y is mostly vertical)
59
+ z = (self.central_blade.position - sample)
60
+ dist = norm(z)
61
+ z = z / dist
62
+ y = cross(cross(z, vector([0, 0, 1.0])), z)
63
+ y = y / norm(y)
64
+ x = cross(y, z) # should have length 1 but normalized in bounding_box
65
+ basis = concat((x, y), dim='basis')
66
+ box = self.bounding_box(basis, unit=dist.unit)
67
+ lengths = box['limits', 1] - box['limits', 0]
68
+ return tuple(2 * atan2(y=e/2, x=dist).to(unit=unit) for e in lengths)
69
+
70
+ def sample_space_angle(self, sample: Variable):
71
+ from scipp import dot, atan2, vector
72
+ z = (self.central_blade.position - sample)
73
+ sample_space_x = vector([1, 0, 0])
74
+ sample_space_y = vector([0, 1, 0])
75
+ return atan2(y=dot(sample_space_y, z), x=dot(sample_space_x, z)).to(unit='radian')
76
+
77
+ def rtp_parameters(self, sample: Variable, oop: Variable):
78
+ from scipp import concat
79
+ p0 = self.central_blade.position
80
+ # exploit that for x in zip returns first all the first elements, then all the second elements, etc.
81
+ x, y, a = [concat(x, dim='blades') for x in zip(*[b.rtp_parameters(sample, p0, oop) for b in self.blades])]
82
+ return x, y, a
83
+
84
+ def mcstas_parameters(self, sample: Variable, source: str, sink: str) -> dict:
85
+ from mccode_antlr.instr import Instance
86
+ from ..spatial import is_scipp_vector
87
+ is_scipp_vector(sample, 'sample')
88
+ source = source.name if isinstance(source, Instance) else source
89
+ sink = sink.name if isinstance(sink, Instance) else sink
90
+ if not isinstance(source, str) or not isinstance(sink, str):
91
+ raise ValueError(f'The source and sink are expected to be str values not {type(source)} and {type(sink)}')
92
+
93
+ perp_q, perp_plane, parallel_q = self.central_blade.shape.to(unit='m').value
94
+ hor_cov, ver_cov = self.coverage(sample)
95
+ params = dict(
96
+ NH=self.count,
97
+ zwidth=perp_q,
98
+ yheight=perp_plane,
99
+ mosaic=self.central_blade.mosaic.to(unit='arcminute').value,
100
+ DM=3.355,
101
+ gap=0.002,
102
+ show_construction='showconstruction',
103
+ angle_h=ver_cov.to(unit='degree').value,
104
+ source=f'"{source}"',
105
+ sink=f'"{sink}"'
106
+ )
107
+ return params
108
+
109
+ def to_mccode(self, assembler: Assembler, source: str, relative: str, sink: str, theta: float, name: str,
110
+ when: str = None, extend: str = None, origin: Variable = None):
111
+ mono = assembler.component(name, 'Monochromator_Rowland',
112
+ at=((0, 0, 0), relative), rotate=((0, theta, 0), relative))
113
+ mono.set_parameters(**self.mcstas_parameters(origin, source, sink))
114
+ mono.WHEN(when)
115
+ mono.EXTEND(extend)
116
+