xrayscatteringtools 0.1.1__tar.gz → 0.2.0__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.
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/.gitattributes +2 -2
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/LICENSE +1 -1
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/PKG-INFO +28 -4
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/README.md +27 -3
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/pyproject.toml +1 -1
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/__init__.py +5 -0
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/calib/__init__.py +2 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/calib/geometry_calibration.py +69 -8
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/calib/scattering_corrections.py +2 -2
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/data/Jungfrau.h5 +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/io.py +114 -6
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/__init__.py +7 -0
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/geometries/SF6__CCSD_T_DHK__aug_cc_pV5Z_DK.h5 +0 -0
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/geometries/make_geometry_h5.py +38 -0
- {xrayscatteringtools-0.1.1/tests → xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/patterns}/convert_ab_initio_to_h5.py +1 -1
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/geometries.py +92 -0
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/geometries.pyi +17 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/theory/iam.py +61 -29
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/theory/patterns.py +6 -6
- xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/patterns.pyi +18 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/utils.py +94 -10
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/DMP_D.xyz +24 -24
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/DMP_L1.xyz +24 -24
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/DMP_L2.xyz +24 -24
- xrayscatteringtools-0.2.0/tests/azav_test.ipynb +107 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/calib_test.ipynb +39 -10
- xrayscatteringtools-0.2.0/tests/geometries_test.ipynb +44 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/iam_oriented_test.ipynb +21 -11
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/iam_pattern_test.ipynb +12 -12
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/patterns_test.ipynb +43 -47
- xrayscatteringtools-0.1.1/src/xrayscatteringtools/__init__.py +0 -3
- xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory/__init__.py +0 -1
- xrayscatteringtools-0.1.1/tests/__init__.py +0 -0
- xrayscatteringtools-0.1.1/tests/sf6_ground.xyz +0 -9
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/.gitignore +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/calib/data/Zn_attenuation_length.h5 +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/epicsArch.py +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/src/xrayscatteringtools/plotting.py +0 -0
- {xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory → xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/IAM}/Compton_Factors.npy +0 -0
- {xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory → xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/IAM}/Scattering_Factors.npy +0 -0
- /xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory/data/SF6_CCSD_aug_cc_pVDZ.h5 → /xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/patterns/SF6__CCSD__aug_cc_pVDZ.h5 +0 -0
- /xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory/data/SF6_HF_aug_cc_pVDZ.h5 → /xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/patterns/SF6__HF__aug_cc_pVDZ.h5 +0 -0
- /xrayscatteringtools-0.1.1/src/xrayscatteringtools/theory/data/SF6_MP2_aug_cc_pVDZ.h5 → /xrayscatteringtools-0.2.0/src/xrayscatteringtools/theory/data/patterns/SF6__MP2__aug_cc_pVDZ.h5 +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/DMP_ground.xyz +0 -0
- {xrayscatteringtools-0.1.1/src/xrayscatteringtools/calib → xrayscatteringtools-0.2.0/tests}/__init__.py +0 -0
- {xrayscatteringtools-0.1.1 → xrayscatteringtools-0.2.0}/tests/sf6_test.xyz +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
# Auto detect text files and perform LF normalization
|
|
2
|
-
* text=auto
|
|
1
|
+
# Auto detect text files and perform LF normalization
|
|
2
|
+
* text=auto
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xrayscatteringtools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A library for gas phase analysis at the CXI endstation
|
|
5
5
|
Project-URL: Homepage, https://github.com/Weber-Group/xrayscatteringtools
|
|
6
6
|
Project-URL: Issues, https://github.com/Weber-Group/xrayscatteringtools/issues
|
|
@@ -29,15 +29,22 @@ Description-Content-Type: text/markdown
|
|
|
29
29
|
|
|
30
30
|
## A python library for the analysis of data from the CXI endstation at the LCLS.
|
|
31
31
|
|
|
32
|
+
### `calib` submodule pertains to the geometry calibration routine
|
|
33
|
+
|
|
34
|
+
### `theory` submodule pertains to stored ab initio patterns, iam, or geometries.
|
|
35
|
+
### `utils` has a bunch of useful functions in it
|
|
36
|
+
### `xrayscatteringtools.io` has anything pertaning to loading or writing data (`combineRuns` is in here)
|
|
37
|
+
### `plotting` has anything to do with plotting.
|
|
38
|
+
|
|
32
39
|
### 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.
|
|
40
|
+
All methods should have full docstrings in the NumPy docstring standard.
|
|
35
41
|
* calib
|
|
36
42
|
* geometry_calibration
|
|
37
43
|
- run_geometry_calibration()
|
|
38
44
|
- model()
|
|
39
45
|
- thompson_correction()
|
|
40
46
|
- geometry_correction()
|
|
47
|
+
- geometry_correction_units()
|
|
41
48
|
* scattering_corrections
|
|
42
49
|
- correction_factor()
|
|
43
50
|
- Si_correction()
|
|
@@ -49,6 +56,7 @@ Proper namespaces have yet to be defined. Some of these functions can remain int
|
|
|
49
56
|
- Al_attenuation_length()
|
|
50
57
|
- Be_attenuation_length()
|
|
51
58
|
- KaptonHN_attenuation_length()
|
|
59
|
+
- Zn_attenuation_length()
|
|
52
60
|
- J4M_efficiency()
|
|
53
61
|
* theory
|
|
54
62
|
* iam
|
|
@@ -56,24 +64,40 @@ Proper namespaces have yet to be defined. Some of these functions can remain int
|
|
|
56
64
|
- iam_inelastic_pattern()
|
|
57
65
|
- iam_total_pattern()
|
|
58
66
|
- iam_compton_spectrum()
|
|
67
|
+
- iam_elastic_pattern_oriented()
|
|
68
|
+
- iam_inelastic_pattern_oriented()
|
|
69
|
+
- iam_total_pattern_oriented()
|
|
59
70
|
* patterns
|
|
60
|
-
-
|
|
71
|
+
- SF6__CCSD__aug_cc_pVDZ
|
|
72
|
+
- SF6__HF__aug_cc_pVDZ
|
|
73
|
+
- SF6__MP2__aug_cc_pVDZ
|
|
74
|
+
* geometries
|
|
75
|
+
- SF6__CCSD_T_DHK__aug_cc_pV5Z_DK
|
|
61
76
|
* io
|
|
62
77
|
- combineRuns()
|
|
63
78
|
- get_tree()
|
|
64
79
|
- is_leaf()
|
|
65
80
|
- get_leaves()
|
|
81
|
+
- get_data_paths()
|
|
66
82
|
- runNumToString()
|
|
67
83
|
- read_xyz()
|
|
84
|
+
- write_xyz()
|
|
85
|
+
- read_mol()
|
|
68
86
|
* plotting
|
|
69
87
|
- plot_jungfrau()
|
|
70
88
|
- compute_pixel_edges()
|
|
71
89
|
* utils
|
|
72
90
|
- enable_underscore_cleanup()
|
|
73
91
|
- azimuthalBinning()
|
|
92
|
+
- au2invAngstroms()
|
|
93
|
+
- invAngstroms2au()
|
|
74
94
|
- keV2Angstroms()
|
|
75
95
|
- Angstroms2keV()
|
|
76
96
|
- q2theta()
|
|
77
97
|
- theta2q()
|
|
78
98
|
- element_symbol_to_number()
|
|
79
99
|
- element_number_to_symbol()
|
|
100
|
+
- translate_molecule()
|
|
101
|
+
- rotate_molecule()
|
|
102
|
+
- J4M()
|
|
103
|
+
-
|
|
@@ -2,15 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## A python library for the analysis of data from the CXI endstation at the LCLS.
|
|
4
4
|
|
|
5
|
+
### `calib` submodule pertains to the geometry calibration routine
|
|
6
|
+
|
|
7
|
+
### `theory` submodule pertains to stored ab initio patterns, iam, or geometries.
|
|
8
|
+
### `utils` has a bunch of useful functions in it
|
|
9
|
+
### `xrayscatteringtools.io` has anything pertaning to loading or writing data (`combineRuns` is in here)
|
|
10
|
+
### `plotting` has anything to do with plotting.
|
|
11
|
+
|
|
5
12
|
### 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.
|
|
13
|
+
All methods should have full docstrings in the NumPy docstring standard.
|
|
8
14
|
* calib
|
|
9
15
|
* geometry_calibration
|
|
10
16
|
- run_geometry_calibration()
|
|
11
17
|
- model()
|
|
12
18
|
- thompson_correction()
|
|
13
19
|
- geometry_correction()
|
|
20
|
+
- geometry_correction_units()
|
|
14
21
|
* scattering_corrections
|
|
15
22
|
- correction_factor()
|
|
16
23
|
- Si_correction()
|
|
@@ -22,6 +29,7 @@ Proper namespaces have yet to be defined. Some of these functions can remain int
|
|
|
22
29
|
- Al_attenuation_length()
|
|
23
30
|
- Be_attenuation_length()
|
|
24
31
|
- KaptonHN_attenuation_length()
|
|
32
|
+
- Zn_attenuation_length()
|
|
25
33
|
- J4M_efficiency()
|
|
26
34
|
* theory
|
|
27
35
|
* iam
|
|
@@ -29,24 +37,40 @@ Proper namespaces have yet to be defined. Some of these functions can remain int
|
|
|
29
37
|
- iam_inelastic_pattern()
|
|
30
38
|
- iam_total_pattern()
|
|
31
39
|
- iam_compton_spectrum()
|
|
40
|
+
- iam_elastic_pattern_oriented()
|
|
41
|
+
- iam_inelastic_pattern_oriented()
|
|
42
|
+
- iam_total_pattern_oriented()
|
|
32
43
|
* patterns
|
|
33
|
-
-
|
|
44
|
+
- SF6__CCSD__aug_cc_pVDZ
|
|
45
|
+
- SF6__HF__aug_cc_pVDZ
|
|
46
|
+
- SF6__MP2__aug_cc_pVDZ
|
|
47
|
+
* geometries
|
|
48
|
+
- SF6__CCSD_T_DHK__aug_cc_pV5Z_DK
|
|
34
49
|
* io
|
|
35
50
|
- combineRuns()
|
|
36
51
|
- get_tree()
|
|
37
52
|
- is_leaf()
|
|
38
53
|
- get_leaves()
|
|
54
|
+
- get_data_paths()
|
|
39
55
|
- runNumToString()
|
|
40
56
|
- read_xyz()
|
|
57
|
+
- write_xyz()
|
|
58
|
+
- read_mol()
|
|
41
59
|
* plotting
|
|
42
60
|
- plot_jungfrau()
|
|
43
61
|
- compute_pixel_edges()
|
|
44
62
|
* utils
|
|
45
63
|
- enable_underscore_cleanup()
|
|
46
64
|
- azimuthalBinning()
|
|
65
|
+
- au2invAngstroms()
|
|
66
|
+
- invAngstroms2au()
|
|
47
67
|
- keV2Angstroms()
|
|
48
68
|
- Angstroms2keV()
|
|
49
69
|
- q2theta()
|
|
50
70
|
- theta2q()
|
|
51
71
|
- element_symbol_to_number()
|
|
52
72
|
- element_number_to_symbol()
|
|
73
|
+
- translate_molecule()
|
|
74
|
+
- rotate_molecule()
|
|
75
|
+
- J4M()
|
|
76
|
+
-
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xrayscatteringtools"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "A library for gas phase analysis at the CXI endstation"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "David Romano", email = "david_j_romano@brown.edu" }
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from .io import combineRuns, get_leaves, read_xyz, write_xyz, read_mol
|
|
2
|
+
from .plotting import plot_jungfrau, compute_pixel_edges
|
|
3
|
+
from .utils import enable_underscore_cleanup, azimuthalBinning, au2invAngstroms, invAngstroms2au, keV2Angstroms, Angstroms2keV, q2theta, theta2q, element_number_to_symbol, element_symbol_to_number, translate_molecule, rotate_molecule, J4M
|
|
4
|
+
from . import theory
|
|
5
|
+
from . import calib
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from scipy.interpolate import InterpolatedUnivariateSpline
|
|
3
3
|
from scipy.optimize import curve_fit
|
|
4
|
-
from
|
|
5
|
-
from
|
|
4
|
+
from ..utils import theta2q
|
|
5
|
+
from .scattering_corrections import correction_factor
|
|
6
6
|
|
|
7
7
|
def run_geometry_calibration(
|
|
8
8
|
raw_image,
|
|
@@ -100,7 +100,22 @@ def run_geometry_calibration(
|
|
|
100
100
|
fit = fitting_function([np.ravel(x), np.ravel(y)], *popt).reshape(raw_image.shape)
|
|
101
101
|
return fit, popt, pcov
|
|
102
102
|
|
|
103
|
-
def model(
|
|
103
|
+
def model(
|
|
104
|
+
xy,
|
|
105
|
+
amplitude,
|
|
106
|
+
x0,
|
|
107
|
+
y0,
|
|
108
|
+
z0,
|
|
109
|
+
phi0,
|
|
110
|
+
photon_energy_keV,
|
|
111
|
+
theory_interpolation,
|
|
112
|
+
do_geometry_correction=True,
|
|
113
|
+
do_thompson_correction=True,
|
|
114
|
+
do_angle_of_scattering_correction=True,
|
|
115
|
+
do_geometry_correction_units=False,
|
|
116
|
+
dx=75,
|
|
117
|
+
dy=75
|
|
118
|
+
):
|
|
104
119
|
"""
|
|
105
120
|
Calculate the theoretical detector image for given geometry parameters.
|
|
106
121
|
|
|
@@ -118,12 +133,25 @@ def model(xy, amplitude, x0, y0, z0, phi0, photon_energy_keV, theory_interpolati
|
|
|
118
133
|
Photon energy in keV.
|
|
119
134
|
theory_interpolation : callable
|
|
120
135
|
Interpolated function for theoretical scattering intensities versus q.
|
|
136
|
+
do_geometry_correction : bool, optional
|
|
137
|
+
If True, apply geometry correction. Default is True.
|
|
138
|
+
do_thompson_correction : bool, optional
|
|
139
|
+
If True, apply Thompson polarization correction. Default is True.
|
|
140
|
+
do_angle_of_scattering_correction : bool, optional
|
|
141
|
+
If True, apply angle-of-scattering correction. Default is True.
|
|
142
|
+
do_geometry_correction_units : bool, optional
|
|
143
|
+
If True, apply geometry accounting for proper solid angle subtension. Default is False.
|
|
144
|
+
dx, dy : float, optional
|
|
145
|
+
Pixel size in microns for geometry correction with units. Default is 75 microns. If do_geometry_correction_units is False, these are ignored.
|
|
121
146
|
|
|
122
147
|
Returns
|
|
123
148
|
-------
|
|
124
149
|
fit : ndarray
|
|
125
150
|
Flattened array of predicted intensities for each pixel.
|
|
126
151
|
|
|
152
|
+
Notes
|
|
153
|
+
-----
|
|
154
|
+
Do not use both do_geometry_correction and do_geometry_correction_units at the same time.
|
|
127
155
|
"""
|
|
128
156
|
# Pull out the x and y arrays from the input
|
|
129
157
|
x = xy[0]
|
|
@@ -138,9 +166,14 @@ def model(xy, amplitude, x0, y0, z0, phi0, photon_energy_keV, theory_interpolati
|
|
|
138
166
|
|
|
139
167
|
# Calculate corrections
|
|
140
168
|
corrections = np.ones_like(q_matrix)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
169
|
+
if do_thompson_correction:
|
|
170
|
+
corrections *= thompson_correction(centered_x, centered_y, z0, phi0) # Polarization
|
|
171
|
+
if do_geometry_correction:
|
|
172
|
+
corrections *= geometry_correction(centered_x, centered_y, z0) # Geometry
|
|
173
|
+
if do_angle_of_scattering_correction:
|
|
174
|
+
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
|
|
175
|
+
if do_geometry_correction_units:
|
|
176
|
+
corrections *= geometry_correction_units(centered_x, centered_y, z0, dx, dy) # Geometry correctly accounting for solid angle subtension per pixel
|
|
144
177
|
fit = amplitude * theory_interpolation(q_matrix) * corrections
|
|
145
178
|
return fit
|
|
146
179
|
|
|
@@ -151,7 +184,7 @@ def thompson_correction(x, y, z0, phi0):
|
|
|
151
184
|
Parameters
|
|
152
185
|
----------
|
|
153
186
|
x, y : ndarray
|
|
154
|
-
Pixel coordinates relative to
|
|
187
|
+
Pixel coordinates relative to signal origin.
|
|
155
188
|
z0 : float
|
|
156
189
|
Detector distance along beam axis.
|
|
157
190
|
phi0 : float
|
|
@@ -181,7 +214,7 @@ def geometry_correction(x, y, z0):
|
|
|
181
214
|
Parameters
|
|
182
215
|
----------
|
|
183
216
|
x, y : ndarray
|
|
184
|
-
Pixel coordinates relative to
|
|
217
|
+
Pixel coordinates relative to signal origin.
|
|
185
218
|
z0 : float
|
|
186
219
|
Detector distance along beam axis.
|
|
187
220
|
|
|
@@ -201,4 +234,32 @@ def geometry_correction(x, y, z0):
|
|
|
201
234
|
r_matrix = np.sqrt(x**2 + y**2)
|
|
202
235
|
theta = np.arctan(r_matrix / z0)
|
|
203
236
|
correction = np.cos(theta) ** 3
|
|
237
|
+
return correction
|
|
238
|
+
|
|
239
|
+
def geometry_correction_units(x, y, z0, dx, dy):
|
|
240
|
+
"""
|
|
241
|
+
Compute geometric correction factor z0^2 cos^3(theta) / dxdy for a detector, accounting for pixel area and distance units.
|
|
242
|
+
|
|
243
|
+
Parameters
|
|
244
|
+
----------
|
|
245
|
+
x, y : ndarray
|
|
246
|
+
Pixel coordinates relative to signal origin.
|
|
247
|
+
z0 : float
|
|
248
|
+
Detector distance along beam axis.
|
|
249
|
+
dx, dy : float
|
|
250
|
+
Pixel size in x and y directions.
|
|
251
|
+
|
|
252
|
+
Returns
|
|
253
|
+
-------
|
|
254
|
+
correction : ndarray
|
|
255
|
+
Geometric correction factor for each pixel.
|
|
256
|
+
|
|
257
|
+
Notes
|
|
258
|
+
-----
|
|
259
|
+
The geometry correction comes from the inverse square law and the effective area of the pixel.
|
|
260
|
+
The inverse square law accounts for z^2 cos^2(theta), and the effective area is cos(theta)/dxdy.
|
|
261
|
+
"""
|
|
262
|
+
r_matrix = np.sqrt(x**2 + y**2)
|
|
263
|
+
theta = np.arctan(r_matrix / z0)
|
|
264
|
+
correction = np.cos(theta)**3 * (dx * dy) / z0**2
|
|
204
265
|
return correction
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from scipy.interpolate import InterpolatedUnivariateSpline
|
|
2
|
-
from
|
|
2
|
+
from ..utils import q2theta
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pathlib
|
|
5
5
|
_data_path = pathlib.Path(__file__).parent / "data"
|
|
@@ -481,7 +481,7 @@ def Zn_attenuation_length(keV):
|
|
|
481
481
|
Uses spline interpolation of tabulated attenuation lengths (in microns),
|
|
482
482
|
then converts them to meters.
|
|
483
483
|
"""
|
|
484
|
-
with h5py.File(
|
|
484
|
+
with h5py.File(f"{_data_path}/Zn_attenuation_length.h5", 'r') as f:
|
|
485
485
|
E_values = f['E_values'][:]
|
|
486
486
|
length = f['length'][:]
|
|
487
487
|
Mu_Spline = InterpolatedUnivariateSpline(E_values, length)
|
|
Binary file
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import h5py
|
|
3
|
-
from
|
|
4
|
-
from xrayscatteringtools.epicsArch import EpicsArchive
|
|
3
|
+
from .epicsArch import EpicsArchive
|
|
5
4
|
from scipy.interpolate import interp1d
|
|
6
5
|
import yaml
|
|
7
|
-
from
|
|
6
|
+
from .utils import element_number_to_symbol
|
|
8
7
|
|
|
9
8
|
def combineRuns(runNumbers, folders, keys_to_combine, keys_to_sum, keys_to_check, verbose=False, archImport=False):
|
|
10
9
|
"""
|
|
@@ -55,6 +54,7 @@ def combineRuns(runNumbers, folders, keys_to_combine, keys_to_sum, keys_to_check
|
|
|
55
54
|
If multiple folders are provided but the number of folders does not match
|
|
56
55
|
the number of run numbers.
|
|
57
56
|
"""
|
|
57
|
+
from tqdm.auto import tqdm # Lazy
|
|
58
58
|
# Ensure runNumbers is a list
|
|
59
59
|
if not isinstance(runNumbers, (list, tuple)):
|
|
60
60
|
runNumbers = [runNumbers]
|
|
@@ -172,7 +172,7 @@ def is_leaf(dataset):
|
|
|
172
172
|
"""
|
|
173
173
|
return isinstance(dataset, h5py.Dataset)
|
|
174
174
|
|
|
175
|
-
def get_leaves(f, saveto, verbose=False):
|
|
175
|
+
def get_leaves(f, saveto=None, verbose=False):
|
|
176
176
|
"""Retrieve all leaf datasets from an HDF5 file and save them to a dictionary.
|
|
177
177
|
|
|
178
178
|
Parameters
|
|
@@ -193,7 +193,8 @@ def get_leaves(f, saveto, verbose=False):
|
|
|
193
193
|
if is_leaf(f[name]):
|
|
194
194
|
if verbose:
|
|
195
195
|
print(name, f[name][()].shape)
|
|
196
|
-
saveto
|
|
196
|
+
if saveto is not None:
|
|
197
|
+
saveto[name] = f[name][()]
|
|
197
198
|
f.visit(return_leaf)
|
|
198
199
|
|
|
199
200
|
def get_data_paths(run_numbers, config_path='config.yaml'):
|
|
@@ -332,4 +333,111 @@ def write_xyz(filename, comment, atoms, coords):
|
|
|
332
333
|
f.write(f"{len(atoms)}\n")
|
|
333
334
|
f.write(f"{comment}\n")
|
|
334
335
|
for atom, (x, y, z) in zip(atoms, coords):
|
|
335
|
-
f.write(f"{atom} {x:.6f} {y:.6f} {z:.6f}\n")
|
|
336
|
+
f.write(f"{atom} {x:.6f} {y:.6f} {z:.6f}\n")
|
|
337
|
+
|
|
338
|
+
def read_mol(filename):
|
|
339
|
+
"""
|
|
340
|
+
Read a molecular structure from a MOL file (MDL Molfile format).
|
|
341
|
+
|
|
342
|
+
Parameters
|
|
343
|
+
----------
|
|
344
|
+
filename : str
|
|
345
|
+
Path to the MOL file to be read.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
molecule_name : str
|
|
350
|
+
Name of the molecule (first line of the file).
|
|
351
|
+
program_info : str
|
|
352
|
+
Program/user information (second line).
|
|
353
|
+
comment : str
|
|
354
|
+
Comment line (third line).
|
|
355
|
+
num_atoms : int
|
|
356
|
+
Number of atoms in the molecule.
|
|
357
|
+
num_bonds : int
|
|
358
|
+
Number of bonds in the molecule.
|
|
359
|
+
atoms : list of str
|
|
360
|
+
List of atomic symbols for each atom.
|
|
361
|
+
coords : list of tuple of float
|
|
362
|
+
Cartesian coordinates of each atom as (x, y, z) in Angstroms.
|
|
363
|
+
bonds : list of tuple of int
|
|
364
|
+
List of bonds as (atom1_index, atom2_index, bond_type).
|
|
365
|
+
Atom indices are 1-based as in the MOL file.
|
|
366
|
+
Bond types: 1=single, 2=double, 3=triple, 4=aromatic.
|
|
367
|
+
properties : dict
|
|
368
|
+
Additional properties from the atom and bond blocks.
|
|
369
|
+
- 'atom_properties': list of dicts with mass_diff, charge, stereo_parity, etc.
|
|
370
|
+
- 'bond_properties': list of dicts with stereo, topology, etc.
|
|
371
|
+
|
|
372
|
+
Notes
|
|
373
|
+
-----
|
|
374
|
+
The MOL file format (V2000) is expected to have:
|
|
375
|
+
1. Line 1: Molecule name
|
|
376
|
+
2. Line 2: Program/user info and timestamp
|
|
377
|
+
3. Line 3: Comment
|
|
378
|
+
4. Line 4: Counts line (atoms, bonds, etc.)
|
|
379
|
+
5. Atom block: one line per atom with coordinates and properties
|
|
380
|
+
6. Bond block: one line per bond
|
|
381
|
+
7. Properties block (optional)
|
|
382
|
+
"""
|
|
383
|
+
with open(filename, 'r') as f:
|
|
384
|
+
lines = f.readlines()
|
|
385
|
+
|
|
386
|
+
# Header block (first 3 lines)
|
|
387
|
+
molecule_name = lines[0].strip()
|
|
388
|
+
program_info = lines[1].strip()
|
|
389
|
+
comment = lines[2].strip()
|
|
390
|
+
|
|
391
|
+
# Counts line (line 4)
|
|
392
|
+
counts_line = lines[3]
|
|
393
|
+
num_atoms = int(counts_line[0:3].strip())
|
|
394
|
+
num_bonds = int(counts_line[3:6].strip())
|
|
395
|
+
|
|
396
|
+
# Atom block
|
|
397
|
+
atoms = []
|
|
398
|
+
coords = []
|
|
399
|
+
atom_properties = []
|
|
400
|
+
|
|
401
|
+
for i in range(4, 4 + num_atoms):
|
|
402
|
+
line = lines[i]
|
|
403
|
+
x = float(line[0:10].strip())
|
|
404
|
+
y = float(line[10:20].strip())
|
|
405
|
+
z = float(line[20:30].strip())
|
|
406
|
+
element = line[31:34].strip()
|
|
407
|
+
|
|
408
|
+
# Additional atom properties
|
|
409
|
+
mass_diff = int(line[34:36].strip()) if len(line) > 34 and line[34:36].strip() else 0
|
|
410
|
+
charge = int(line[36:39].strip()) if len(line) > 36 and line[36:39].strip() else 0
|
|
411
|
+
|
|
412
|
+
atoms.append(element)
|
|
413
|
+
coords.append((x, y, z))
|
|
414
|
+
atom_properties.append({
|
|
415
|
+
'mass_diff': mass_diff,
|
|
416
|
+
'charge': charge
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
# Bond block
|
|
420
|
+
bonds = []
|
|
421
|
+
bond_properties = []
|
|
422
|
+
|
|
423
|
+
bond_start = 4 + num_atoms
|
|
424
|
+
for i in range(bond_start, bond_start + num_bonds):
|
|
425
|
+
line = lines[i]
|
|
426
|
+
atom1 = int(line[0:3].strip())
|
|
427
|
+
atom2 = int(line[3:6].strip())
|
|
428
|
+
bond_type = int(line[6:9].strip())
|
|
429
|
+
|
|
430
|
+
# Additional bond properties
|
|
431
|
+
stereo = int(line[9:12].strip()) if len(line) > 9 and line[9:12].strip() else 0
|
|
432
|
+
|
|
433
|
+
bonds.append((atom1, atom2, bond_type))
|
|
434
|
+
bond_properties.append({
|
|
435
|
+
'stereo': stereo
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
properties = {
|
|
439
|
+
'atom_properties': atom_properties,
|
|
440
|
+
'bond_properties': bond_properties
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return molecule_name, program_info, comment, num_atoms, num_bonds, atoms, coords, bonds, properties
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from .iam import iam_total_pattern, iam_elastic_pattern, iam_inelastic_pattern
|
|
2
|
+
from .iam import iam_total_pattern_oriented, iam_elastic_pattern_oriented, iam_inelastic_pattern_oriented
|
|
3
|
+
from .iam import iam_compton_spectrum
|
|
4
|
+
|
|
5
|
+
from .geometries import SF6__CCSD_T_DHK__aug_cc_pV5Z_DK
|
|
6
|
+
|
|
7
|
+
from .patterns import SF6__CCSD__aug_cc_pVDZ, SF6__MP2__aug_cc_pVDZ, SF6__HF__aug_cc_pVDZ
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import h5py
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
# Naming convention "Molecule__Method__Basis__Extras"
|
|
5
|
+
filename = "SF6__CCSD_T_DHK__aug_cc_pV5Z_DK"
|
|
6
|
+
molecule = "SF6"
|
|
7
|
+
method = "CCSD(T)+DHK"
|
|
8
|
+
basis_set = "aug-cc-pV5Z-DK"
|
|
9
|
+
n_electrons = 70
|
|
10
|
+
energy = -998.01159357
|
|
11
|
+
notes = "+DKH means that scalar-relativistic corrections via a tenth-order Douglas-Kroll-Hess Hamiltonian are included. This is also reflected by the -DK in the basis set. Mats Simmermacher sent over on Nov 17, 2025."
|
|
12
|
+
atoms = ['S', 'F', 'F', 'F', 'F', 'F', 'F']
|
|
13
|
+
charge = 0
|
|
14
|
+
geometry = np.array([
|
|
15
|
+
[ 0.0000000000, 0.0000000000, 0.0000000000],
|
|
16
|
+
[ 0.0000000000, 0.0000000000, 1.5600310790],
|
|
17
|
+
[ 0.0000000000, 0.0000000000, -1.5600310790],
|
|
18
|
+
[ 0.0000000000, 1.5600310790, 0.0000000000],
|
|
19
|
+
[ 0.0000000000, -1.5600310790, 0.0000000000],
|
|
20
|
+
[ 1.5600310790, 0.0000000000, 0.0000000000],
|
|
21
|
+
[-1.5600310790, 0.0000000000, 0.0000000000]
|
|
22
|
+
])
|
|
23
|
+
|
|
24
|
+
# Creating the file and saving it
|
|
25
|
+
with h5py.File(filename + ".h5", "w") as f:
|
|
26
|
+
|
|
27
|
+
# Attributes
|
|
28
|
+
f.attrs["molecule"] = molecule
|
|
29
|
+
f.attrs["method"] = method
|
|
30
|
+
f.attrs["basis_set"] = basis_set
|
|
31
|
+
f.attrs["n_electrons"] = n_electrons
|
|
32
|
+
f.attrs["energy"] = energy
|
|
33
|
+
f.attrs["notes"] = notes
|
|
34
|
+
f.attrs["charge"] = charge
|
|
35
|
+
f.attrs["atoms"] = atoms
|
|
36
|
+
|
|
37
|
+
# Datasets
|
|
38
|
+
f.create_dataset("geometry", data=geometry)
|
|
@@ -17,7 +17,7 @@ molecule = "SF6"
|
|
|
17
17
|
method = "HF"
|
|
18
18
|
basis_set = "aug_cc_pVDZ"
|
|
19
19
|
##################### End User Set Parameters #####################
|
|
20
|
-
h5_filename = f"{molecule}
|
|
20
|
+
h5_filename = f"{molecule}__{method}__{basis_set}.h5"
|
|
21
21
|
|
|
22
22
|
# Current conversion from a.u. to 1/Angstrom
|
|
23
23
|
conversion_factor = au2invAngstroms(1.0)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
import h5py
|
|
3
|
+
import pathlib
|
|
4
|
+
|
|
5
|
+
# Generally the import names go like 'molecule_method_basisset' Put all available names in __all__. These should match the .h5 files in the data directory.
|
|
6
|
+
__all__ = [
|
|
7
|
+
'SF6__CCSD_T_DHK__aug_cc_pV5Z_DK'
|
|
8
|
+
]
|
|
9
|
+
def __dir__():
|
|
10
|
+
# Tab completion for IPython
|
|
11
|
+
return sorted(__all__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_data_path = pathlib.Path(__file__).parent / "data/geometries"
|
|
15
|
+
|
|
16
|
+
def __getattr__(name):
|
|
17
|
+
if name in __all__:
|
|
18
|
+
# Load from HDF5 only when first accessed
|
|
19
|
+
with h5py.File(f"{_data_path}/{name}.h5", "r") as f:
|
|
20
|
+
obj = _make_default_obj(f)
|
|
21
|
+
obj.__doc__ = _make_default_docstring(obj)
|
|
22
|
+
return obj
|
|
23
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
24
|
+
|
|
25
|
+
def _make_default_obj(f):
|
|
26
|
+
"""
|
|
27
|
+
Create a SimpleNamespace object with default attributes from an HDF5 file.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
f : h5py.File
|
|
32
|
+
An open HDF5 file object containing the datasets and attributes.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
obj : SimpleNamespace
|
|
37
|
+
A SimpleNamespace object with attributes: geometry, molecule, method, basis_set, n_electrons, charge, energy, atoms, notes.
|
|
38
|
+
"""
|
|
39
|
+
return SimpleNamespace(
|
|
40
|
+
geometry=f["geometry"][:],
|
|
41
|
+
molecule=f.attrs["molecule"],
|
|
42
|
+
method=f.attrs["method"],
|
|
43
|
+
basis_set=f.attrs["basis_set"],
|
|
44
|
+
n_electrons=f.attrs["n_electrons"],
|
|
45
|
+
charge=f.attrs["charge"],
|
|
46
|
+
energy=f.attrs["energy"],
|
|
47
|
+
atoms=f.attrs["atoms"],
|
|
48
|
+
notes=f.attrs["notes"]
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def _make_default_docstring(obj):
|
|
52
|
+
"""
|
|
53
|
+
Generate a default docstring for a geometry object.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
obj : SimpleNamespace
|
|
58
|
+
The data object with attributes: geometry, molecule, method, basis_set, n_electrons.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
doc : str
|
|
63
|
+
The generated docstring.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
doc = f"""
|
|
67
|
+
Optimized geometry for {obj.molecule} at the {obj.method}/{obj.basis_set} level of theory.
|
|
68
|
+
|
|
69
|
+
Attributes
|
|
70
|
+
----------
|
|
71
|
+
geometry : Nx3 numpy array
|
|
72
|
+
The geometry data of the molecule, in Angstroms.
|
|
73
|
+
atoms : list of str
|
|
74
|
+
The list of atomic symbols corresponding to the geometry.
|
|
75
|
+
molecule : str
|
|
76
|
+
The molecular formula of the species.
|
|
77
|
+
method : str
|
|
78
|
+
The method used for the calculation.
|
|
79
|
+
basis_set : str
|
|
80
|
+
The basis set used for the calculation.
|
|
81
|
+
n_electrons : int
|
|
82
|
+
The number of electrons in the molecule.
|
|
83
|
+
charge : int
|
|
84
|
+
The net charge of the molecule.
|
|
85
|
+
energy : float
|
|
86
|
+
The total electronic energy of the molecule in Hartree.
|
|
87
|
+
|
|
88
|
+
Notes
|
|
89
|
+
-----
|
|
90
|
+
{obj.notes}
|
|
91
|
+
"""
|
|
92
|
+
return doc
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
|
|
3
|
+
__all__: list[str]
|
|
4
|
+
|
|
5
|
+
class _GeometryData(SimpleNamespace):
|
|
6
|
+
"""Type stub for ab initio geometry data."""
|
|
7
|
+
geometry: any # ndarray
|
|
8
|
+
molecule: str
|
|
9
|
+
method: str
|
|
10
|
+
basis_set: str
|
|
11
|
+
n_electrons: int
|
|
12
|
+
charge: int
|
|
13
|
+
energy: float
|
|
14
|
+
atoms: list[str]
|
|
15
|
+
notes: str
|
|
16
|
+
|
|
17
|
+
SF6__CCSD_T_DHK__aug_cc_pV5Z_DK: _GeometryData
|