xrayscatteringtools 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 (28) hide show
  1. xrayscatteringtools-0.0.1/.gitattributes +2 -0
  2. xrayscatteringtools-0.0.1/.gitignore +181 -0
  3. xrayscatteringtools-0.0.1/LICENSE +21 -0
  4. xrayscatteringtools-0.0.1/PKG-INFO +79 -0
  5. xrayscatteringtools-0.0.1/README.md +52 -0
  6. xrayscatteringtools-0.0.1/pyproject.toml +59 -0
  7. xrayscatteringtools-0.0.1/src/xrayscatteringtools/__init__.py +3 -0
  8. xrayscatteringtools-0.0.1/src/xrayscatteringtools/calib/__init__.py +0 -0
  9. xrayscatteringtools-0.0.1/src/xrayscatteringtools/calib/geometry_calibration.py +204 -0
  10. xrayscatteringtools-0.0.1/src/xrayscatteringtools/calib/scattering_corrections.py +488 -0
  11. xrayscatteringtools-0.0.1/src/xrayscatteringtools/epicsArch.py +392 -0
  12. xrayscatteringtools-0.0.1/src/xrayscatteringtools/io.py +310 -0
  13. xrayscatteringtools-0.0.1/src/xrayscatteringtools/plotting.py +88 -0
  14. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/Compton_Factors.npy +0 -0
  15. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/Scattering_Factors.npy +0 -0
  16. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/__init__.py +1 -0
  17. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/data/sf6.h5 +0 -0
  18. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/iam.py +213 -0
  19. xrayscatteringtools-0.0.1/src/xrayscatteringtools/theory/patterns.py +36 -0
  20. xrayscatteringtools-0.0.1/src/xrayscatteringtools/utils.py +456 -0
  21. xrayscatteringtools-0.0.1/tests/DMP_D.xyz +24 -0
  22. xrayscatteringtools-0.0.1/tests/DMP_L1.xyz +24 -0
  23. xrayscatteringtools-0.0.1/tests/DMP_L2.xyz +24 -0
  24. xrayscatteringtools-0.0.1/tests/DMP_ground.xyz +24 -0
  25. xrayscatteringtools-0.0.1/tests/__init__.py +0 -0
  26. xrayscatteringtools-0.0.1/tests/calib_test.ipynb +127 -0
  27. xrayscatteringtools-0.0.1/tests/iam_pattern_test.ipynb +149 -0
  28. xrayscatteringtools-0.0.1/tests/sf6_ground.xyz +9 -0
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
@@ -0,0 +1,181 @@
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
+ # Ruff stuff:
171
+ .ruff_cache/
172
+
173
+ # PyPI configuration file
174
+ .pypirc
175
+
176
+ # Cursor
177
+ # Cursor is an AI-powered code editor.`.cursorignore` specifies files/directories to
178
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
179
+ # refer to https://docs.cursor.com/context/ignore-files
180
+ .cursorignore
181
+ .cursorindexingignore
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Romano
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.
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: xrayscatteringtools
3
+ Version: 0.0.1
4
+ Summary: A library for gas phase analysis at the CXI endstation
5
+ Project-URL: Homepage, https://github.com/Weber-Group/xrayscatteringtools
6
+ Project-URL: Issues, https://github.com/Weber-Group/xrayscatteringtools/issues
7
+ Author-email: David Romano <david_j_romano@brown.edu>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.9
11
+ Requires-Dist: h5py
12
+ Requires-Dist: ipython
13
+ Requires-Dist: matplotlib
14
+ Requires-Dist: numpy<2
15
+ Requires-Dist: pathlib
16
+ Requires-Dist: pyyaml
17
+ Requires-Dist: requests
18
+ Requires-Dist: scipy>=1.11
19
+ Requires-Dist: tqdm
20
+ Requires-Dist: xraylib
21
+ Provides-Extra: dev
22
+ Requires-Dist: black>=24.0; extra == 'dev'
23
+ Requires-Dist: mypy>=1.9; extra == 'dev'
24
+ Requires-Dist: pytest>=8.0; extra == 'dev'
25
+ Requires-Dist: ruff>=0.3; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # xrayscatteringtools
29
+
30
+ ## A python library for the analysis of data from the CXI endstation at the LCLS.
31
+
32
+ ### List of all methods:
33
+ All methods have full docstrings in the NumPy docstring standard.
34
+ Proper namespaces have yet to be defined. Some of these functions can remain internal, and the more useful ones can be defined at the surface level.
35
+ * calib
36
+ * geometry_calibration
37
+ - run_geometry_calibration()
38
+ - model()
39
+ - thompson_correction()
40
+ - geometry_correction()
41
+ * scattering_corrections
42
+ - correction_factor()
43
+ - Si_correction()
44
+ - KaptonHN_correction()
45
+ - Al_correction()
46
+ - Be_correction()
47
+ - cell_correction()
48
+ - Si_attenuation_length()
49
+ - Al_attenuation_length()
50
+ - Be_attenuation_length()
51
+ - KaptonHN_attenuation_length()
52
+ - J4M_efficiency()
53
+ * theory
54
+ * iam
55
+ - iam_elastic_pattern()
56
+ - iam_inelastic_pattern()
57
+ - iam_total_pattern()
58
+ - iam_compton_spectrum()
59
+ * patterns
60
+ - sf6()
61
+ * io
62
+ - combineRuns()
63
+ - get_tree()
64
+ - is_leaf()
65
+ - get_leaves()
66
+ - runNumToString()
67
+ - read_xyz()
68
+ * plotting
69
+ - plot_jungfrau()
70
+ - compute_pixel_edges()
71
+ * utils
72
+ - enable_underscore_cleanup()
73
+ - azimuthalBinning()
74
+ - keV2Angstroms()
75
+ - Angstroms2keV()
76
+ - q2theta()
77
+ - theta2q()
78
+ - element_symbol_to_number()
79
+ - element_number_to_symbol()
@@ -0,0 +1,52 @@
1
+ # xrayscatteringtools
2
+
3
+ ## A python library for the analysis of data from the CXI endstation at the LCLS.
4
+
5
+ ### List of all methods:
6
+ All methods have full docstrings in the NumPy docstring standard.
7
+ Proper namespaces have yet to be defined. Some of these functions can remain internal, and the more useful ones can be defined at the surface level.
8
+ * calib
9
+ * geometry_calibration
10
+ - run_geometry_calibration()
11
+ - model()
12
+ - thompson_correction()
13
+ - geometry_correction()
14
+ * scattering_corrections
15
+ - correction_factor()
16
+ - Si_correction()
17
+ - KaptonHN_correction()
18
+ - Al_correction()
19
+ - Be_correction()
20
+ - cell_correction()
21
+ - Si_attenuation_length()
22
+ - Al_attenuation_length()
23
+ - Be_attenuation_length()
24
+ - KaptonHN_attenuation_length()
25
+ - J4M_efficiency()
26
+ * theory
27
+ * iam
28
+ - iam_elastic_pattern()
29
+ - iam_inelastic_pattern()
30
+ - iam_total_pattern()
31
+ - iam_compton_spectrum()
32
+ * patterns
33
+ - sf6()
34
+ * io
35
+ - combineRuns()
36
+ - get_tree()
37
+ - is_leaf()
38
+ - get_leaves()
39
+ - runNumToString()
40
+ - read_xyz()
41
+ * plotting
42
+ - plot_jungfrau()
43
+ - compute_pixel_edges()
44
+ * utils
45
+ - enable_underscore_cleanup()
46
+ - azimuthalBinning()
47
+ - keV2Angstroms()
48
+ - Angstroms2keV()
49
+ - q2theta()
50
+ - theta2q()
51
+ - element_symbol_to_number()
52
+ - element_number_to_symbol()
@@ -0,0 +1,59 @@
1
+ [build-system]
2
+ requires = ["hatchling >= 1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "xrayscatteringtools"
7
+ version = "0.0.1"
8
+ description = "A library for gas phase analysis at the CXI endstation"
9
+ authors = [
10
+ { name = "David Romano", email = "david_j_romano@brown.edu" }
11
+ ]
12
+ readme = "README.md"
13
+ license = "MIT"
14
+ license-files = ["LICEN[CS]E*"]
15
+ requires-python = ">=3.9"
16
+ dependencies = [
17
+ "numpy<2",
18
+ "scipy>=1.11",
19
+ "pathlib",
20
+ "IPython",
21
+ "matplotlib",
22
+ "tqdm",
23
+ "h5py",
24
+ "requests",
25
+ "xraylib",
26
+ "pyyaml"
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "pytest>=8.0",
32
+ "black>=24.0",
33
+ "mypy>=1.9",
34
+ "ruff>=0.3"
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/Weber-Group/xrayscatteringtools"
39
+ Issues = "https://github.com/Weber-Group/xrayscatteringtools/issues"
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
43
+
44
+ [tool.pytest.ini_options]
45
+ testpaths = ["tests"]
46
+ addopts = "-ra -q"
47
+
48
+ [tool.black]
49
+ line-length = 88
50
+ target-version = ["py310"]
51
+
52
+ [tool.ruff]
53
+ line-length = 88
54
+ select = ["E", "F", "W"]
55
+ ignore = ["E501"]
56
+
57
+ [tool.mypy]
58
+ python_version = "3.10"
59
+ strict = true
@@ -0,0 +1,3 @@
1
+ from .io import *
2
+ from .plotting import *
3
+ from .utils import *
@@ -0,0 +1,204 @@
1
+ import numpy as np
2
+ from scipy.interpolate import InterpolatedUnivariateSpline
3
+ from scipy.optimize import curve_fit
4
+ from xrayscatteringtools.utils import theta2q
5
+ from xrayscatteringtools.calib.scattering_corrections import correction_factor
6
+
7
+ def run_geometry_calibration(
8
+ raw_image,
9
+ x,
10
+ y,
11
+ mask,
12
+ theory_q,
13
+ theory_Iq,
14
+ photon_energy_keV,
15
+ initial_guess={'amplitude' : 1,'x0': 0, 'y0': 0, 'z0': 90000},
16
+ polarization = 0,
17
+ mask_center=True,
18
+ mask_center_size=7500,
19
+ bounds = ([0, -10_000, -10_000, 30_000], [np.inf, 10_000, 10_000, 150_000])
20
+ ):
21
+ """
22
+ Perform geometry calibration on a raw detector image using a theoretical scattering pattern.
23
+
24
+ This function fits the detector geometry parameters (x0, y0, z0) by comparing the
25
+ measured image to a theoretical scattering pattern and applying corrections for
26
+ polarization (Thompson), geometry, and angle-of-scattering effects.
27
+
28
+ Parameters
29
+ ----------
30
+ raw_image : ndarray
31
+ Array of measured intensities from the detector.
32
+ x : ndarray
33
+ Array of x-coordinates for each pixel.
34
+ y : ndarray
35
+ Array of y-coordinates for each pixel.
36
+ mask : ndarray of bool
37
+ Boolean mask array indicating which pixels to include in the fit.
38
+ theory_q : ndarray
39
+ 1D array of scattering vector magnitudes corresponding to the theoretical pattern.
40
+ theory_Iq : ndarray
41
+ 1D array of theoretical scattering intensities at each q.
42
+ photon_energy_keV : float
43
+ Photon energy of the X-ray in keV.
44
+ initial_guess : dict, optional
45
+ Initial guess for fit parameters:
46
+ - 'amplitude' : float, scaling of the intensity
47
+ - 'x0', 'y0', 'z0' : float, initial guesses for detector geometry
48
+ Default: {'amplitude': 1, 'x0': 0, 'y0': 0, 'z0': 90000}.
49
+ polarization : float, optional
50
+ Polarization direction (-pi/2 to pi/2). Default is 0 (horizontally polarized).
51
+ mask_center : bool, optional
52
+ If True, exclude pixels near the center from the fit. Default is True.
53
+ mask_center_size : float, optional
54
+ Radius (in pixels) of the excluded central region. Default is 7500.
55
+ fit_bounds : tuple of array_like, optional
56
+ Lower and upper bounds for the fit parameters. Default is
57
+ ([0, -10000, -10000, 30000, -π/2], [inf, 10000, 10000, 150000, π/2]).
58
+
59
+ Returns
60
+ -------
61
+ fit : ndarray
62
+ 3D array representing the fitted detector image (reshaped to match input dimensions).
63
+ popt : ndarray
64
+ Optimized fit parameters: [amplitude, x0, y0, z0]. In units of microns.
65
+ pcov : ndarray
66
+ Covariance matrix of the optimized parameters.
67
+
68
+ Notes
69
+ -----
70
+ The returned z0 distance must be converted to millimeters when editing the producer. It should not be in microns.
71
+ The fitting applies:
72
+ - `thompson_correction` for polarization effects,
73
+ - `geometry_correction` for geometric distortions,
74
+ - `correction_factor` for angle-of-scattering corrections (Lingyu Ma et al 2024 J. Phys. B: At. Mol. Opt. Phys. 57 205602).
75
+
76
+ Examples
77
+ --------
78
+ >>> fit, popt, pcov = run_geometry_calibration(raw_image, x, y, mask, theory_q, theory_Iq, 12.7)
79
+ """
80
+ # Step one: generate an interpolation for the theory pattern.
81
+ theory_interpolation = InterpolatedUnivariateSpline(theory_q, theory_Iq, ext=3) # Extrapolation 3. Returns Boundary value if outside of range.
82
+
83
+ # Step two: Define initial guess, bounds, and fitting function using a wrapper
84
+ p0 = [initial_guess['amplitude'], initial_guess['x0'], initial_guess['y0'], initial_guess['z0']]
85
+ def fitting_function(xy, amplitude, x0, y0, z0):
86
+ return model(xy, amplitude, x0, y0, z0, polarization, photon_energy_keV, theory_interpolation)
87
+
88
+ # Step three: Masking and formatting variables
89
+ center_mask = np.ones_like(raw_image, dtype=bool)
90
+ if mask_center:
91
+ center_mask[np.sqrt(x**2 + y**2) < mask_center_size] = False
92
+
93
+ masked_data = np.ravel(raw_image[mask & center_mask])
94
+ x_masked = np.ravel(x[mask & center_mask])
95
+ y_masked = np.ravel(y[mask & center_mask])
96
+ xy_masked = [x_masked, y_masked]
97
+
98
+ # Step four: fitting the data
99
+ popt, pcov = curve_fit(fitting_function, xy_masked, masked_data, p0=p0, bounds=bounds)
100
+ fit = fitting_function([np.ravel(x), np.ravel(y)], *popt).reshape(raw_image.shape)
101
+ return fit, popt, pcov
102
+
103
+ def model(xy, amplitude, x0, y0, z0, phi0, photon_energy_keV, theory_interpolation):
104
+ """
105
+ Calculate the theoretical detector image for given geometry parameters.
106
+
107
+ Parameters
108
+ ----------
109
+ xy : list of ndarray
110
+ [x, y] 2D arrays of pixel coordinates.
111
+ amplitude : float
112
+ Scaling factor for intensity.
113
+ x0, y0, z0 : float
114
+ Detector geometry parameters (pixel offsets and distance).
115
+ phi0 : float
116
+ Azimuthal rotation angle in radians.
117
+ photon_energy_keV : float
118
+ Photon energy in keV.
119
+ theory_interpolation : callable
120
+ Interpolated function for theoretical scattering intensities versus q.
121
+
122
+ Returns
123
+ -------
124
+ fit : ndarray
125
+ Flattened array of predicted intensities for each pixel.
126
+
127
+ """
128
+ # Pull out the x and y arrays from the input
129
+ x = xy[0]
130
+ y = xy[1]
131
+ # Center the arrays around x0 and y0
132
+ centered_x = x - x0
133
+ centered_y = y - y0
134
+ # Calculate the r array
135
+ r_matrix = np.sqrt(centered_x**2 + centered_y**2)
136
+ theta_matrix = np.arctan(r_matrix/z0)
137
+ q_matrix = theta2q(theta_matrix, photon_energy_keV)
138
+
139
+ # Calculate corrections
140
+ corrections = np.ones_like(q_matrix)
141
+ corrections *= thompson_correction(centered_x, centered_y, z0, phi0) # Polarization
142
+ corrections *= geometry_correction(centered_x, centered_y, z0) # Geometry
143
+ corrections *= correction_factor(q_matrix, photon_energy_keV) # Angle-Of-Scattering, Lingyu Ma et al 2024 J. Phys. B: At. Mol. Opt. Phys. 57 205602
144
+ fit = amplitude * theory_interpolation(q_matrix) * corrections
145
+ return fit
146
+
147
+ def thompson_correction(x, y, z0, phi0):
148
+ """
149
+ Calculate the Thompson polarization correction for each pixel.
150
+
151
+ Parameters
152
+ ----------
153
+ x, y : ndarray
154
+ Pixel coordinates relative to detector origin.
155
+ z0 : float
156
+ Detector distance along beam axis.
157
+ phi0 : float
158
+ Azimuthal rotation angle in radians.
159
+
160
+ Returns
161
+ -------
162
+ correction : ndarray
163
+ Thompson correction factor for each pixel.
164
+
165
+ Notes
166
+ -----
167
+ See Lingyu Ma et al 2024 J. Phys. B: At. Mol. Opt. Phys. 57 205602
168
+
169
+ """
170
+ # Calculate the Thompson scattering correction factor
171
+ r_matrix = np.sqrt(x**2 + y**2)
172
+ theta = np.arctan(r_matrix/z0)
173
+ phi = np.arctan2(y, x) + phi0
174
+ correction = np.sin(phi)**2+np.cos(theta)**2*np.cos(phi)**2
175
+ return correction
176
+
177
+ def geometry_correction(x, y, z0):
178
+ """
179
+ Compute geometric correction factor (cos^3(theta)) for a detector.
180
+
181
+ Parameters
182
+ ----------
183
+ x, y : ndarray
184
+ Pixel coordinates relative to detector origin.
185
+ z0 : float
186
+ Detector distance along beam axis.
187
+
188
+ Returns
189
+ -------
190
+ correction : ndarray
191
+ Geometric correction factor for each pixel.
192
+
193
+ Notes
194
+ -----
195
+ The geometry correction comes from the inverse square law and the effective area of the pixel.
196
+ The inverse square law accounts for cos^2(theta), and the effective area is another cos(theta).
197
+ See Lingyu Ma et al 2024 J. Phys. B: At. Mol. Opt. Phys. 57 205602
198
+
199
+
200
+ """
201
+ r_matrix = np.sqrt(x**2 + y**2)
202
+ theta = np.arctan(r_matrix / z0)
203
+ correction = np.cos(theta) ** 3
204
+ return correction