xrheed 0.5.13__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.
- xrheed-0.5.13/LICENSE +21 -0
- xrheed-0.5.13/PKG-INFO +135 -0
- xrheed-0.5.13/README.md +99 -0
- xrheed-0.5.13/pyproject.toml +47 -0
- xrheed-0.5.13/setup.cfg +4 -0
- xrheed-0.5.13/src/xrheed/__init__.py +61 -0
- xrheed-0.5.13/src/xrheed/conversion/__init__.py +9 -0
- xrheed-0.5.13/src/xrheed/conversion/base.py +120 -0
- xrheed-0.5.13/src/xrheed/conversion/image.py +138 -0
- xrheed-0.5.13/src/xrheed/io.py +76 -0
- xrheed-0.5.13/src/xrheed/kinematics/__init__.py +10 -0
- xrheed-0.5.13/src/xrheed/kinematics/cache_utils.py +50 -0
- xrheed-0.5.13/src/xrheed/kinematics/ewald.py +645 -0
- xrheed-0.5.13/src/xrheed/kinematics/lattice.py +455 -0
- xrheed-0.5.13/src/xrheed/plotting/__init__.py +11 -0
- xrheed-0.5.13/src/xrheed/plotting/base.py +116 -0
- xrheed-0.5.13/src/xrheed/plotting/overview.py +75 -0
- xrheed-0.5.13/src/xrheed/plotting/profiles.py +82 -0
- xrheed-0.5.13/src/xrheed/plugins/__init__.py +114 -0
- xrheed-0.5.13/src/xrheed/plugins/dsnp_arpes_bmp.py +77 -0
- xrheed-0.5.13/src/xrheed/plugins/dsnp_arpes_raw.py +109 -0
- xrheed-0.5.13/src/xrheed/preparation/__init__.py +9 -0
- xrheed-0.5.13/src/xrheed/preparation/alignment.py +195 -0
- xrheed-0.5.13/src/xrheed/preparation/filters.py +114 -0
- xrheed-0.5.13/src/xrheed/xarray_accessors.py +476 -0
- xrheed-0.5.13/src/xrheed.egg-info/PKG-INFO +135 -0
- xrheed-0.5.13/src/xrheed.egg-info/SOURCES.txt +33 -0
- xrheed-0.5.13/src/xrheed.egg-info/dependency_links.txt +1 -0
- xrheed-0.5.13/src/xrheed.egg-info/requires.txt +19 -0
- xrheed-0.5.13/src/xrheed.egg-info/top_level.txt +1 -0
- xrheed-0.5.13/tests/test_conversion.py +35 -0
- xrheed-0.5.13/tests/test_data_loading.py +96 -0
- xrheed-0.5.13/tests/test_ewald.py +82 -0
- xrheed-0.5.13/tests/test_lattice.py +127 -0
- xrheed-0.5.13/tests/test_preparation.py +38 -0
xrheed-0.5.13/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Marek Kopciuszynski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
xrheed-0.5.13/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xrheed
|
|
3
|
+
Version: 0.5.13
|
|
4
|
+
Summary: An xarray-based toolkit for RHEED image analysis
|
|
5
|
+
Author-email: Marek Kopciuszynski <mkopciuszynski@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: RHEED,diffraction,xarray,analysis
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: xarray>=0.18.2
|
|
18
|
+
Requires-Dist: numpy>=1.21.0
|
|
19
|
+
Requires-Dist: scipy>=1.7.0
|
|
20
|
+
Requires-Dist: matplotlib>=3.4.2
|
|
21
|
+
Requires-Dist: ruptures>=1.1.7
|
|
22
|
+
Requires-Dist: tqdm>=4.62.0
|
|
23
|
+
Requires-Dist: lmfit>=1.1.0
|
|
24
|
+
Requires-Dist: dill>=0.3.4
|
|
25
|
+
Requires-Dist: Pillow>=9.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: ruff; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest; extra == "dev"
|
|
29
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
30
|
+
Requires-Dist: myst-parser; extra == "dev"
|
|
31
|
+
Requires-Dist: myst-nb; extra == "dev"
|
|
32
|
+
Requires-Dist: nbsphinx; extra == "dev"
|
|
33
|
+
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
34
|
+
Requires-Dist: build; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# xRHEED
|
|
38
|
+
|
|
39
|
+
📡 An **xarray-based toolkit** for RHEED image analysis.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
[](https://github.com/mkopciuszynski/xrheed/actions/workflows/ci.yml)
|
|
44
|
+
[](https://xrheed.readthedocs.io/en/latest/?badge=latest)
|
|
45
|
+
[](https://pypi.org/project/xrheed/)
|
|
46
|
+
[](https://opensource.org/licenses/MIT)
|
|
47
|
+
[](https://github.com/psf/black)
|
|
48
|
+
[](https://github.com/astral-sh/ruff)
|
|
49
|
+
[](https://github.com/astral-sh/uv)
|
|
50
|
+
[](https://doi.org/10.5281/zenodo.xxxxx)
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🔬 What is RHEED?
|
|
55
|
+
|
|
56
|
+
**Reflection High-Energy Electron Diffraction (RHEED)** is an experimental technique used to monitor and control the quality of crystal surfaces.
|
|
57
|
+
A high-energy electron beam (∼20 keV) strikes the surface at a grazing angle (< 5°), making the method highly **surface-sensitive** and probing only a few atomic layers.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🎯 Project Goals
|
|
62
|
+
|
|
63
|
+
**xRHEED** provides a flexible and extensible **Python toolkit** for RHEED image analysis:
|
|
64
|
+
|
|
65
|
+
- 🖼️ Load and preprocess RHEED images
|
|
66
|
+
- 📈 Generate and analyze intensity profiles
|
|
67
|
+
- ✨ Overlay predicted diffraction spot positions (kinematic theory & Ewald construction)
|
|
68
|
+
- 🔄 Transform RHEED images into kx–ky space
|
|
69
|
+
- 🔍 Search for reconstruction lattice constants and rotations by calculating the matching coefficient between predicted and experimental data
|
|
70
|
+
|
|
71
|
+
👉 **Note:** xRHEED is **not a GUI application**. It is designed as an **xarray accessory library**, intended for use in **interactive environments** such as Jupyter notebooks.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## ⚡ Installation
|
|
76
|
+
|
|
77
|
+
You can install **xRHEED** using either [`uv`](https://github.com/astral-sh/uv) or `pip`.
|
|
78
|
+
|
|
79
|
+
### Using pip (editable install for development)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/mkopciuszynski/xrheed
|
|
83
|
+
cd xrheed
|
|
84
|
+
pip install -e .
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Using uv (with a virtual environment)
|
|
88
|
+
|
|
89
|
+
1. Install [`uv`](https://docs.astral.sh/uv/guides/projects/).
|
|
90
|
+
2. Clone the repository:
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/mkopciuszynski/xrheed
|
|
93
|
+
cd xrheed
|
|
94
|
+
```
|
|
95
|
+
3. Create and activate a virtual environment (depending on your shell: bash, zsh, fish, PowerShell).
|
|
96
|
+
4. Sync dependencies:
|
|
97
|
+
```bash
|
|
98
|
+
uv sync
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 🚀 Quick Usage
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
import matplotlib.pyplot as plt
|
|
107
|
+
import xrheed
|
|
108
|
+
from xrheed.io import load_data
|
|
109
|
+
|
|
110
|
+
# Load a RHEED image
|
|
111
|
+
rheed_image = load_data("rheed_image.raw", plugin="dsnp_arpes_raw")
|
|
112
|
+
|
|
113
|
+
# Show image with auto-adjusted levels
|
|
114
|
+
rheed_image.ri.plot_image(auto_levels=2.0)
|
|
115
|
+
plt.show()
|
|
116
|
+
|
|
117
|
+
# Get intensity profile and plot its origin
|
|
118
|
+
profile = rheed_image.ri.get_profile(center=(0, -5), width=40, height=4,
|
|
119
|
+
plot_origin=True)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 📖 Citation
|
|
125
|
+
|
|
126
|
+
If you use **xRHEED** in your research, please consider citing this repository:
|
|
127
|
+
|
|
128
|
+
> Kopciuszynski, M. (2025). *xRHEED: An xarray-based toolkit for RHEED image analysis*.
|
|
129
|
+
> GitHub. https://github.com/mkopciuszynski/xrheed
|
|
130
|
+
|
|
131
|
+
📌 A formal DOI will be provided in the future via [Zenodo](https://zenodo.org/).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
📚 👉 See the [full documentation](https://xrheed.readthedocs.io/en/latest/) for tutorials and advanced examples.
|
xrheed-0.5.13/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# xRHEED
|
|
2
|
+
|
|
3
|
+
📡 An **xarray-based toolkit** for RHEED image analysis.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
[](https://github.com/mkopciuszynski/xrheed/actions/workflows/ci.yml)
|
|
8
|
+
[](https://xrheed.readthedocs.io/en/latest/?badge=latest)
|
|
9
|
+
[](https://pypi.org/project/xrheed/)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://github.com/psf/black)
|
|
12
|
+
[](https://github.com/astral-sh/ruff)
|
|
13
|
+
[](https://github.com/astral-sh/uv)
|
|
14
|
+
[](https://doi.org/10.5281/zenodo.xxxxx)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🔬 What is RHEED?
|
|
19
|
+
|
|
20
|
+
**Reflection High-Energy Electron Diffraction (RHEED)** is an experimental technique used to monitor and control the quality of crystal surfaces.
|
|
21
|
+
A high-energy electron beam (∼20 keV) strikes the surface at a grazing angle (< 5°), making the method highly **surface-sensitive** and probing only a few atomic layers.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🎯 Project Goals
|
|
26
|
+
|
|
27
|
+
**xRHEED** provides a flexible and extensible **Python toolkit** for RHEED image analysis:
|
|
28
|
+
|
|
29
|
+
- 🖼️ Load and preprocess RHEED images
|
|
30
|
+
- 📈 Generate and analyze intensity profiles
|
|
31
|
+
- ✨ Overlay predicted diffraction spot positions (kinematic theory & Ewald construction)
|
|
32
|
+
- 🔄 Transform RHEED images into kx–ky space
|
|
33
|
+
- 🔍 Search for reconstruction lattice constants and rotations by calculating the matching coefficient between predicted and experimental data
|
|
34
|
+
|
|
35
|
+
👉 **Note:** xRHEED is **not a GUI application**. It is designed as an **xarray accessory library**, intended for use in **interactive environments** such as Jupyter notebooks.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## ⚡ Installation
|
|
40
|
+
|
|
41
|
+
You can install **xRHEED** using either [`uv`](https://github.com/astral-sh/uv) or `pip`.
|
|
42
|
+
|
|
43
|
+
### Using pip (editable install for development)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/mkopciuszynski/xrheed
|
|
47
|
+
cd xrheed
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Using uv (with a virtual environment)
|
|
52
|
+
|
|
53
|
+
1. Install [`uv`](https://docs.astral.sh/uv/guides/projects/).
|
|
54
|
+
2. Clone the repository:
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/mkopciuszynski/xrheed
|
|
57
|
+
cd xrheed
|
|
58
|
+
```
|
|
59
|
+
3. Create and activate a virtual environment (depending on your shell: bash, zsh, fish, PowerShell).
|
|
60
|
+
4. Sync dependencies:
|
|
61
|
+
```bash
|
|
62
|
+
uv sync
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🚀 Quick Usage
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import matplotlib.pyplot as plt
|
|
71
|
+
import xrheed
|
|
72
|
+
from xrheed.io import load_data
|
|
73
|
+
|
|
74
|
+
# Load a RHEED image
|
|
75
|
+
rheed_image = load_data("rheed_image.raw", plugin="dsnp_arpes_raw")
|
|
76
|
+
|
|
77
|
+
# Show image with auto-adjusted levels
|
|
78
|
+
rheed_image.ri.plot_image(auto_levels=2.0)
|
|
79
|
+
plt.show()
|
|
80
|
+
|
|
81
|
+
# Get intensity profile and plot its origin
|
|
82
|
+
profile = rheed_image.ri.get_profile(center=(0, -5), width=40, height=4,
|
|
83
|
+
plot_origin=True)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 📖 Citation
|
|
89
|
+
|
|
90
|
+
If you use **xRHEED** in your research, please consider citing this repository:
|
|
91
|
+
|
|
92
|
+
> Kopciuszynski, M. (2025). *xRHEED: An xarray-based toolkit for RHEED image analysis*.
|
|
93
|
+
> GitHub. https://github.com/mkopciuszynski/xrheed
|
|
94
|
+
|
|
95
|
+
📌 A formal DOI will be provided in the future via [Zenodo](https://zenodo.org/).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
📚 👉 See the [full documentation](https://xrheed.readthedocs.io/en/latest/) for tutorials and advanced examples.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "xrheed"
|
|
3
|
+
version = "0.5.13"
|
|
4
|
+
authors = [
|
|
5
|
+
{name = "Marek Kopciuszynski", email = "mkopciuszynski@gmail.com"},
|
|
6
|
+
]
|
|
7
|
+
description = "An xarray-based toolkit for RHEED image analysis"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
keywords = ["RHEED", "diffraction", "xarray", "analysis"]
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Topic :: Scientific/Engineering",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"xarray>=0.18.2",
|
|
23
|
+
"numpy>=1.21.0",
|
|
24
|
+
"scipy>=1.7.0",
|
|
25
|
+
"matplotlib>=3.4.2",
|
|
26
|
+
"ruptures>=1.1.7",
|
|
27
|
+
"tqdm>=4.62.0",
|
|
28
|
+
"lmfit>=1.1.0",
|
|
29
|
+
"dill>=0.3.4",
|
|
30
|
+
"Pillow>=9.0.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["setuptools>=61", "wheel", "build"]
|
|
35
|
+
build-backend = "setuptools.build_meta"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = [
|
|
39
|
+
"ruff",
|
|
40
|
+
"pytest",
|
|
41
|
+
"sphinx",
|
|
42
|
+
"myst-parser",
|
|
43
|
+
"myst-nb",
|
|
44
|
+
"nbsphinx",
|
|
45
|
+
"sphinx-rtd-theme",
|
|
46
|
+
"build",
|
|
47
|
+
]
|
xrheed-0.5.13/setup.cfg
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
xRHEED: An xarray-based toolkit for RHEED image analysis.
|
|
3
|
+
|
|
4
|
+
This package provides tools to:
|
|
5
|
+
- Load and preprocess RHEED images
|
|
6
|
+
- Extract and analyze intensity profiles
|
|
7
|
+
- Transform images to kx-ky space
|
|
8
|
+
- Predict and visualize diffraction spot positions using kinematic theory and Ewald construction
|
|
9
|
+
xRHEED is designed as an **xarray accessory library** for interactive analysis
|
|
10
|
+
in environments such as Jupyter notebooks. It is **not a GUI application**.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import importlib
|
|
14
|
+
import logging
|
|
15
|
+
import pkgutil
|
|
16
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
17
|
+
|
|
18
|
+
# Import xarray accessors
|
|
19
|
+
from . import xarray_accessors as xarray_accessors
|
|
20
|
+
|
|
21
|
+
# Package version
|
|
22
|
+
try:
|
|
23
|
+
__version__ = version("xrheed")
|
|
24
|
+
except PackageNotFoundError:
|
|
25
|
+
__version__ = "0.0.0"
|
|
26
|
+
|
|
27
|
+
# Configure logging
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
logger.info(f"xrheed {__version__} initialized successfully. Accessors registered.")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Check if running inside a Jupyter notebook
|
|
33
|
+
def _in_jupyter():
|
|
34
|
+
try:
|
|
35
|
+
from IPython import get_ipython
|
|
36
|
+
|
|
37
|
+
shell = get_ipython()
|
|
38
|
+
return shell is not None and shell.__class__.__name__ == "ZMQInteractiveShell"
|
|
39
|
+
except Exception:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Show a welcome message in Jupyter
|
|
44
|
+
if _in_jupyter():
|
|
45
|
+
print(f"\n🎉 xrheed v{__version__} loaded!")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Plugin discovery
|
|
49
|
+
def discover_plugins():
|
|
50
|
+
try:
|
|
51
|
+
import xrheed.plugins
|
|
52
|
+
|
|
53
|
+
for _, module_name, is_pkg in pkgutil.iter_modules(xrheed.plugins.__path__):
|
|
54
|
+
if not is_pkg:
|
|
55
|
+
importlib.import_module(f"xrheed.plugins.{module_name}")
|
|
56
|
+
except Exception as e:
|
|
57
|
+
logger.warning(f"Plugin discovery failed: {e}")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Run plugin discovery after all imports
|
|
61
|
+
discover_plugins()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Submodule `conversion` handles coordinate and unit conversions for RHEED images,
|
|
3
|
+
e.g., transforming between pixel space and kx-ky space.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .base import convert_gx_gy_to_sx_sy, convert_sx_to_ky
|
|
7
|
+
from .image import transform_image_to_kxky
|
|
8
|
+
|
|
9
|
+
__all__ = ["convert_gx_gy_to_sx_sy", "convert_sx_to_ky", "transform_image_to_kxky"]
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from typing import Optional, Tuple
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.typing import NDArray
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def convert_sx_to_ky(
|
|
8
|
+
x_coords_mm: NDArray,
|
|
9
|
+
ewald_sphere_radius: float,
|
|
10
|
+
screen_sample_distance_mm: float,
|
|
11
|
+
) -> NDArray:
|
|
12
|
+
"""Convert sx coordinates from mm to ky [1/Å] using the Ewald sphere radius and screen-sample distance.
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
x_coords_mm : NDArray
|
|
16
|
+
Array of x coordinates in millimeters (mm).
|
|
17
|
+
ewald_sphere_radius : float
|
|
18
|
+
Radius of the Ewald sphere in reciprocal space (1/Å).
|
|
19
|
+
screen_sample_distance_mm : float
|
|
20
|
+
Distance from the sample to the screen in millimeters (mm).
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
NDArray
|
|
25
|
+
Converted x coordinates in ky [1/Å].
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
kx: NDArray = (x_coords_mm / screen_sample_distance_mm) * ewald_sphere_radius
|
|
29
|
+
|
|
30
|
+
return kx
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def convert_gx_gy_to_sx_sy(
|
|
34
|
+
gx: NDArray[np.float32],
|
|
35
|
+
gy: NDArray[np.float32],
|
|
36
|
+
ewald_radius: float,
|
|
37
|
+
beta: float,
|
|
38
|
+
screen_sample_distance: float,
|
|
39
|
+
remove_outside: Optional[bool] = True,
|
|
40
|
+
**kwargs,
|
|
41
|
+
) -> Tuple[NDArray[np.float32], NDArray[np.float32]]:
|
|
42
|
+
"""
|
|
43
|
+
Convert reciprocal lattice coordinates (gx, gy) to RHEED screen coordinates (sx, sy)
|
|
44
|
+
using the Ewald sphere construction.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
gx : NDArray
|
|
49
|
+
Array of reciprocal lattice x-coordinates.
|
|
50
|
+
gy : NDArray
|
|
51
|
+
Array of reciprocal lattice y-coordinates.
|
|
52
|
+
ewald_radius : float
|
|
53
|
+
Radius of the Ewald sphere in reciprocal space (1/Å or same units as gx, gy).
|
|
54
|
+
beta : float
|
|
55
|
+
Incident beam angle in degrees relative to the surface normal.
|
|
56
|
+
screen_sample_distance : float
|
|
57
|
+
Distance from the sample to the detector/screen.
|
|
58
|
+
remove_outside : Optional[bool], default=True
|
|
59
|
+
If True, points outside the Ewald sphere are removed.
|
|
60
|
+
If False, points outside are set to NaN.
|
|
61
|
+
**kwargs
|
|
62
|
+
Additional keyword arguments (currently unused).
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
sx : NDArray
|
|
67
|
+
Array of x-coordinates on the RHEED screen corresponding to input gx, gy.
|
|
68
|
+
sy : NDArray
|
|
69
|
+
Array of y-coordinates on the RHEED screen corresponding to input gx, gy.
|
|
70
|
+
|
|
71
|
+
Notes
|
|
72
|
+
-----
|
|
73
|
+
- The function assumes a simple planar screen perpendicular to the z-axis.
|
|
74
|
+
- The coordinate transformation accounts for the Ewald sphere geometry
|
|
75
|
+
and the projection of diffraction spots onto the screen.
|
|
76
|
+
- `beta` is the incident angle of the electron beam relative to the sample surface.
|
|
77
|
+
- Points outside the Ewald sphere can be optionally removed or set as NaN
|
|
78
|
+
using the `remove_outside` flag.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
# Ewald sphere radius
|
|
82
|
+
k0: np.float32 = np.float32(ewald_radius)
|
|
83
|
+
# Ewald sphere radius square
|
|
84
|
+
kk: np.float32 = np.float32(k0**2)
|
|
85
|
+
|
|
86
|
+
# calculate the shift between the center of Ewald sphere and the center of reciprocal lattice
|
|
87
|
+
delta_x: np.float32 = np.float32(k0 * np.cos(np.deg2rad(beta)))
|
|
88
|
+
|
|
89
|
+
# shift the center of reciprocal lattice
|
|
90
|
+
kx: NDArray[np.float32] = gx + delta_x
|
|
91
|
+
ky: NDArray[np.float32] = gy
|
|
92
|
+
|
|
93
|
+
# Check if the kx, ky points are inside Ewald sphere
|
|
94
|
+
kxy2: NDArray[np.float32] = kx**2 + ky**2
|
|
95
|
+
|
|
96
|
+
ind: NDArray[np.bool_] = kxy2 < kk
|
|
97
|
+
|
|
98
|
+
# remove those outside or mark as nans
|
|
99
|
+
if remove_outside:
|
|
100
|
+
kx = kx[ind]
|
|
101
|
+
ky = ky[ind]
|
|
102
|
+
else:
|
|
103
|
+
kx[~ind] = np.nan
|
|
104
|
+
ky[~ind] = np.nan
|
|
105
|
+
|
|
106
|
+
# calculate the radius r_k
|
|
107
|
+
rk: NDArray[np.float32] = np.sqrt(k0**2 - kx**2)
|
|
108
|
+
|
|
109
|
+
# calculate theta and phi (cos) values
|
|
110
|
+
phi: NDArray[np.float32] = np.arccos(ky / rk)
|
|
111
|
+
theta: NDArray[np.float32] = np.arcsin(rk / k0)
|
|
112
|
+
|
|
113
|
+
# calculate the radius on the RHEED screen
|
|
114
|
+
rho: NDArray[np.float32] = screen_sample_distance * np.tan(theta)
|
|
115
|
+
|
|
116
|
+
# calculate the spot positions
|
|
117
|
+
sx: NDArray[np.float32] = rho * np.cos(phi)
|
|
118
|
+
sy: NDArray[np.float32] = -rho * np.sin(phi)
|
|
119
|
+
|
|
120
|
+
return sx, sy
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import xarray as xr
|
|
3
|
+
from numpy.typing import NDArray
|
|
4
|
+
from scipy import ndimage # type: ignore
|
|
5
|
+
|
|
6
|
+
from .base import convert_gx_gy_to_sx_sy
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def transform_image_to_kxky(
|
|
10
|
+
rheed_image: xr.DataArray,
|
|
11
|
+
rotate: bool = False,
|
|
12
|
+
point_symmetry: bool = False,
|
|
13
|
+
) -> xr.DataArray:
|
|
14
|
+
"""
|
|
15
|
+
Transform the RHEED image to kx-ky coordinates.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
rotate : bool, optional
|
|
20
|
+
If True, rotate the transformed image (default: True).
|
|
21
|
+
mirror : bool, optional
|
|
22
|
+
If True, add mirrored image (default: False).
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
xr.DataArray
|
|
27
|
+
Transformed image in kx-ky coordinates.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# prepare the data for calculations
|
|
31
|
+
screen_sample_distance: float = rheed_image.ri.screen_sample_distance
|
|
32
|
+
beta: float = rheed_image.ri.beta
|
|
33
|
+
alpha: float = rheed_image.ri.alpha
|
|
34
|
+
|
|
35
|
+
ewald_radius: float = np.sqrt(rheed_image.ri.beam_energy) * 0.5123
|
|
36
|
+
|
|
37
|
+
# new coordinates for transformation
|
|
38
|
+
# TODO add the parameter that allows to set kx, ky
|
|
39
|
+
kx: NDArray[np.float32] = np.arange(-10, 10, 0.01, dtype=np.float32)
|
|
40
|
+
ky: NDArray[np.float32] = np.arange(-10, 10, 0.01, dtype=np.float32)
|
|
41
|
+
|
|
42
|
+
gx: NDArray[np.float32]
|
|
43
|
+
gy: NDArray[np.float32]
|
|
44
|
+
|
|
45
|
+
gx, gy = np.meshgrid(kx, ky, indexing="ij")
|
|
46
|
+
|
|
47
|
+
sx_to_kx: NDArray[np.float32]
|
|
48
|
+
sy_to_ky: NDArray[np.float32]
|
|
49
|
+
|
|
50
|
+
sx_to_kx, sy_to_ky = convert_gx_gy_to_sx_sy(
|
|
51
|
+
gx,
|
|
52
|
+
gy,
|
|
53
|
+
ewald_radius=ewald_radius,
|
|
54
|
+
beta=beta,
|
|
55
|
+
screen_sample_distance=screen_sample_distance,
|
|
56
|
+
remove_outside=False,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# relation between old and new
|
|
60
|
+
sx: xr.DataArray = xr.DataArray(
|
|
61
|
+
sx_to_kx, dims=["kx", "ky"], coords={"kx": kx, "ky": ky}
|
|
62
|
+
)
|
|
63
|
+
sy: xr.DataArray = xr.DataArray(
|
|
64
|
+
sy_to_ky, dims=["kx", "ky"], coords={"kx": kx, "ky": ky}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
trans_image: xr.DataArray = rheed_image.interp(sx=sx, sy=sy, method="linear")
|
|
68
|
+
|
|
69
|
+
if rotate:
|
|
70
|
+
trans_image_rotated = _rotate_trans_image(trans_image, alpha)
|
|
71
|
+
trans_image = trans_image_rotated
|
|
72
|
+
|
|
73
|
+
if point_symmetry:
|
|
74
|
+
trans_image_rotated = _rotate_trans_image(trans_image, 180)
|
|
75
|
+
trans_image = xr.where(np.isnan(trans_image), trans_image_rotated, trans_image)
|
|
76
|
+
|
|
77
|
+
trans_image.attrs = rheed_image.attrs
|
|
78
|
+
|
|
79
|
+
return trans_image
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _rotate_trans_image(
|
|
83
|
+
trans_image: xr.DataArray, angle: float, mode: str = "nearest"
|
|
84
|
+
) -> xr.DataArray:
|
|
85
|
+
"""
|
|
86
|
+
Rotate a 2D xarray.DataArray around its center by a given angle.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
rheed_image : xr.DataArray
|
|
91
|
+
2D image-like DataArray to rotate.
|
|
92
|
+
angle : float
|
|
93
|
+
Rotation angle in degrees (counter-clockwise).
|
|
94
|
+
mode : str
|
|
95
|
+
How to handle values outside boundaries ('constant', 'nearest', 'reflect', ...).
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
rotated : xr.DataArray
|
|
100
|
+
Rotated DataArray with NaNs preserved.
|
|
101
|
+
"""
|
|
102
|
+
if trans_image.ndim != 2:
|
|
103
|
+
raise ValueError("rotate_xarray expects a 2D DataArray")
|
|
104
|
+
|
|
105
|
+
# Assert that coordinates exist
|
|
106
|
+
if "kx" not in trans_image.coords or "ky" not in trans_image.coords:
|
|
107
|
+
raise ValueError("rotate_xarray requires coordinates 'kx' and 'ky'")
|
|
108
|
+
|
|
109
|
+
# Assert that kx and ky are identical
|
|
110
|
+
if not np.allclose(trans_image["kx"].values, trans_image["ky"].values):
|
|
111
|
+
raise ValueError("rotate_xarray requires kx and ky coordinates to be identical")
|
|
112
|
+
|
|
113
|
+
# Build mask for NaNs
|
|
114
|
+
nan_mask: NDArray[np.bool_] = ~np.isnan(trans_image.values)
|
|
115
|
+
filled: xr.DataArray = trans_image.fillna(0)
|
|
116
|
+
|
|
117
|
+
# Rotate data and mask
|
|
118
|
+
rotated_data: NDArray[np.uint8] = ndimage.rotate(
|
|
119
|
+
filled.values, angle, reshape=False, mode=mode, order=1
|
|
120
|
+
).astype(np.uint8)
|
|
121
|
+
|
|
122
|
+
rotated_mask: NDArray[np.bool_] = (
|
|
123
|
+
ndimage.rotate(
|
|
124
|
+
nan_mask.astype(np.uint8), angle, reshape=False, mode=mode, order=0
|
|
125
|
+
)
|
|
126
|
+
> 0
|
|
127
|
+
).astype(np.bool)
|
|
128
|
+
|
|
129
|
+
# Wrap back into DataArray, reusing same coords/dims
|
|
130
|
+
rotated = xr.DataArray(
|
|
131
|
+
rotated_data,
|
|
132
|
+
coords=trans_image.coords,
|
|
133
|
+
dims=trans_image.dims,
|
|
134
|
+
attrs=trans_image.attrs,
|
|
135
|
+
name=trans_image.name,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return rotated.where(rotated_mask)
|