xrayscatteringtools 0.0.1__py3-none-any.whl

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.
@@ -0,0 +1,456 @@
1
+ import re
2
+ from IPython import get_ipython
3
+ import numpy as np
4
+
5
+ def enable_underscore_cleanup():
6
+ """
7
+ Register a Jupyter Notebook post-cell hook to automatically delete user-defined
8
+ single-underscore variables after each cell execution.
9
+
10
+ Notes
11
+ -----
12
+ This helps keep the notebook namespace clean by removing temporary variables
13
+ that start with a single underscore (`_`) but are not standard IPython variables
14
+ (like `_i`, `_oh`, etc.) or Python "dunder" variables.
15
+ """
16
+ ipython = get_ipython()
17
+ user_ns = ipython.user_ns # This gives you access to the Jupyter notebook namespace
18
+
19
+ def clean_user_underscore_vars(*args, **kwargs):
20
+ def is_user_defined_underscore(var):
21
+ return (
22
+ var.startswith('_')
23
+ and not re.match(r'^_i\d*$|^_\d*$|^_ih$|^_oh$|^_ii*$|^_iii$|^_dh$|^_$', var)
24
+ and not var.startswith('__')
25
+ )
26
+
27
+ for var in list(user_ns):
28
+ if is_user_defined_underscore(var):
29
+ del user_ns[var]
30
+
31
+ ipython.events.register('post_run_cell', clean_user_underscore_vars)
32
+
33
+ def azimuthalBinning(
34
+ img,
35
+ x,
36
+ y,
37
+ x0 = 0,
38
+ y0 = 0,
39
+ z0 = 90000,
40
+ tx = 0,
41
+ ty = 0,
42
+ keV = 10,
43
+ pPlane = 0,
44
+ threshADU = [0,np.inf],
45
+ threshRMS = None,
46
+ mask = None,
47
+ qBin = 0.05,
48
+ rBin = None,
49
+ phiBins = 1,
50
+ geomCorr = True,
51
+ polCorr = True,
52
+ darkImg = None,
53
+ gainImg = None,
54
+ z_off = 0,
55
+ square = False,
56
+ debug = False
57
+ ):
58
+ """Performs azimuthal binning of a 2D image.
59
+
60
+ This function integrates a 2D detector image into a 1D profile as a
61
+ function of a radial coordinate (either momentum transfer 'q' or
62
+ real-space radius 'r'). It can perform this integration in multiple
63
+ azimuthal sectors ('phi'). The geometry of the setup, including detector
64
+ distance, tilt, and beam center, is taken into account. Optional
65
+ corrections for polarization are also provided.
66
+
67
+ Parameters
68
+ ----------
69
+ img : np.ndarray
70
+ The input image data to be binned.
71
+ x, y : np.ndarray
72
+ Arrays of the same shape as `img` representing the pixel
73
+ x and y coordinates. Default for Jungfrau4M is in micron.
74
+ x0, y0 : float
75
+ x and y-coordinates of the beam center in detector coordinates (J4M: micron). Default is 0.
76
+ z0 : float
77
+ Sample-to-detector distance in detector coordinates (J4M: micron). Default is 90000.
78
+ tx, ty : float, optional
79
+ Detector tilt angles around the y and x axes, respectively, in degrees.
80
+ Default is 0.
81
+ kev : float, optional
82
+ Photon energy of the incident beam in keV. Required for q-space
83
+ binning. Default is 10.
84
+ p_plane : {0, 1}, optional
85
+ The polarization plane of the incident beam.
86
+ 1 for vertical polarization, 0 for horizontal. Default is 0.
87
+ threshADU : tuple(float, float), optional
88
+ (min, max) threshold in ADU. Pixel values outside this range are
89
+ set to 0 for the binning calculation. Default is (0, np.inf).
90
+ threshRMS : float, optional
91
+ RMS threshold. Pixel values above this are set to 0. Default is None.
92
+ mask : np.ndarray, optional
93
+ A boolean or integer array of the same shape as `img`. A value of
94
+ True or 1 indicates a pixel to be excluded from the analysis. If none,
95
+ no pixels are excluded. Default is None.
96
+ qBin : float or array_like, optional
97
+ If a float, it's the size of each q-bin in inverse Angstroms (Å⁻¹).
98
+ If an array, it specifies the bin edges for non-uniform binning.
99
+ This parameter is ignored if `r_bin` is specified. Default is 0.05 Å⁻¹.
100
+ rBin : float or array_like, optional
101
+ If specified, binning is performed in real-space radius 'r' (in pixels)
102
+ instead of q-space. If a float, it is the bin size. If an array,
103
+ it specifies the bin edges. Default is None.
104
+ phiBins : int or array_like, optional
105
+ If an int, it's the number of uniform azimuthal bins.
106
+ If an array, it specifies the bin edges in radians for non-uniform
107
+ azimuthal sectors. Default is 1 (no azimuthal binning).
108
+ geom_corr : bool, optional
109
+ If True, apply a geometric (solid angle) correction. Default is True.
110
+ pol_corr : bool, optional
111
+ If True, apply a polarization (Thompson) correction. Default is True.
112
+ dark_img : np.ndarray, optional
113
+ A dark image to be subtracted from `img`. Default is None.
114
+ gain_img : np.ndarray, optional
115
+ A gain/flat-field image to divide `img` by. Default is None.
116
+ z_off : float or np.ndarray, optional
117
+ An additional offset along the beam direction (z-axis) in pixels.
118
+ Default is 0.
119
+ square : bool, optional
120
+ If True, the image is squared before binning. Default is False.
121
+ debug : bool, optional
122
+ If True, print debugging information. Default is False.
123
+
124
+ Returns
125
+ -------
126
+ radial_centers : np.ndarray
127
+ 1D array of the center values for each radial bin (either q in Å⁻¹
128
+ or r in detector coordinates (J4M: micron).
129
+ azimuthal_average : np.ndarray
130
+ The binned data. A 2D array of shape (`n_phi_bins`, `n_radial_bins`)
131
+ or a 1D array if `phi_bins` is 1.
132
+
133
+ Notes
134
+ -----
135
+ - The geometric and angular calculations are based on the methodology
136
+ described in J. Chem. Phys. 113, 9140 (2000).
137
+ - The function preserves the original's specific, non-standard behavior
138
+ of placing pixels that fall outside the defined bin ranges into the
139
+ first bin.
140
+ - The normalization (pixel count per bin) includes all pixels, but the
141
+ intensity summation only includes unmasked pixels. This matches the
142
+ original's logic but may affect the normalization of the first bin if
143
+ a mask is used, as masked pixels are assigned to bin 0 for the count.
144
+
145
+ Examples
146
+ --------
147
+ >>> radial_centers, azimuthal_average = azimuthalBinning(img, x, y)
148
+ >>> radial_centers, azimuthal_average = azimuthalBinning(img, x, y, x0=100, y0=150, z0=95000, keV=12.7, qBin=0.02, phiBins=8)
149
+ """
150
+
151
+ # --- 1. Image Preprocessing ---
152
+ # Apply dark and gain corrections if provided
153
+ if darkImg is not None:
154
+ img = img - darkImg
155
+ if gainImg is not None:
156
+ img = img / gainImg
157
+ if square:
158
+ img = img ** 2
159
+ threshold_mask = (img < threshADU[0]) | (img > threshADU[1])
160
+ if threshRMS is not None:
161
+ threshold_mask |= (img > threshRMS)
162
+ if mask is None:
163
+ mask = np.zeros_like(img, dtype=bool)
164
+
165
+ # --- 2. Geometric Transformations ---
166
+ tx_rad, ty_rad = np.deg2rad(tx), np.deg2rad(ty)
167
+ z_total = z0 + z_off
168
+
169
+ # Geometric parameters from J Chem Phys 113, 9140 (2000)
170
+ A = -np.sin(ty_rad) * np.cos(tx_rad)
171
+ B = -np.sin(tx_rad)
172
+ C = -np.cos(ty_rad) * np.cos(tx_rad)
173
+ a = x0 + z_total * np.tan(ty_rad)
174
+ b = y0 - z_total * np.tan(tx_rad)
175
+ c = z_total
176
+
177
+ # Transforming (x,y) to r, theta, phi
178
+ r = np.sqrt((x - a) ** 2 + (y - b) ** 2 + c ** 2)
179
+ matrix_theta = np.arccos((A * (x - a) + B * (y - b) - C * c) / r)
180
+ with np.errstate(invalid='ignore'):
181
+ matrix_phi = np.arccos(
182
+ ((A**2 + C**2) * (y - b) - A * B * (x - a) + B * C * c)
183
+ / np.sqrt((A**2 + C**2) * (r**2 - (A * (x - a) + B * (y - b) - C * c) ** 2))
184
+ )
185
+
186
+ # Correct NaN values and wrap phi to [0, 2pi]
187
+ matrix_phi[(y >= y0) & (np.isnan(matrix_phi))] = 0
188
+ matrix_phi[(y < y0) & (np.isnan(matrix_phi))] = np.pi
189
+ matrix_phi[x < x0] = 2 * np.pi - matrix_phi[x < x0]
190
+
191
+ # --- 3 Correction Factor Calculations ---
192
+ # Default to ones if no correction is applied
193
+ geom_correction = np.ones_like(img, dtype=float)
194
+ pol_correction = np.ones_like(img, dtype=float)
195
+
196
+ if geomCorr:
197
+ # Solid angle correction.
198
+ geom_correction = (z_total / r**3)
199
+ geom_correction /= np.nanmax(geom_correction)
200
+
201
+ if polCorr:
202
+ # Polarization or Thompson correction. This is a mixing term, not just a pure polarization correction.
203
+ Pout = 1 - pPlane
204
+ pol_correction = Pout * (
205
+ 1 - (np.sin(matrix_phi) * np.sin(matrix_theta)) ** 2
206
+ ) + pPlane * (1 - (np.cos(matrix_phi) * np.sin(matrix_theta)) ** 2)
207
+
208
+ correction = geom_correction * pol_correction
209
+
210
+ # --- 4. Binning Setup ---
211
+ # Azimuthal, (phi) binning
212
+ if isinstance(phiBins, (list, np.ndarray)):
213
+ phi_edges = np.sort(np.asarray(phiBins))
214
+ # Ensure range is fully covered for dgitization
215
+ if phi_edges.max() < (2 * np.pi - 0.01):
216
+ phi_edges = np.append(phi_edges, phi_edges.max() + 0.001)
217
+ if phi_edges.min() > 0:
218
+ phi_edges = np.insert(phi_edges, 0, phi_edges.min() - 0.001)
219
+ n_phi_bins = len(phi_edges) - 1
220
+ else:
221
+ n_phi_bins = phiBins
222
+ phi_min, phi_max = np.nanmin(matrix_phi), np.nanmax(matrix_phi)
223
+ phi_edges = np.linspace(phi_min, phi_max, n_phi_bins + 1)
224
+
225
+ # Radial (q or r) binning
226
+ if rBin is not None:
227
+ # Binning in real-space radius (r)
228
+ radial_map = np.sqrt((x - x0) ** 2 + (y - y0) ** 2)
229
+ r_min = np.nanmin(radial_map[~mask])
230
+ r_max = np.nanmax(radial_map[~mask])
231
+
232
+ if np.isscalar (rBin):
233
+ if debug: print("r-bin size given: rmax: ", r_max, " rBin ", rBin)
234
+ radial_edges = np.arange(r_min - rBin, r_max + rBin, rBin)
235
+ else:
236
+ radial_edges = np.asarray(rBin)
237
+ radial_centers = (radial_edges[:-1] + radial_edges[1:]) / 2
238
+ n_radial_bins = len(radial_centers)
239
+ else:
240
+ # Binning in reciprocal space (q)
241
+ lam = keV2Angstroms(keV)
242
+ radial_map = 4 * np.pi / lam * np.sin(matrix_theta / 2)
243
+ q_min = np.nanmin(radial_map[~mask])
244
+ q_max = np.nanmax(radial_map[~mask])
245
+
246
+ if np.isscalar(qBin):
247
+ if debug: print("q-bin size given: qmax: ", q_max, " qBin ", qBin)
248
+ radial_edges = np.arange(0, q_max + qBin, qBin)
249
+ else:
250
+ radial_edges = np.asarray(qBin)
251
+ radial_centers = (radial_edges[:-1] + radial_edges[1:]) / 2
252
+ n_radial_bins = len(radial_centers)
253
+
254
+ # --- 5. Binning Assignment ---
255
+ # Shift phi map slightly to handle edge cases
256
+ phi_step = (phi_edges[1] - phi_edges[0]) / 2 if len(phi_edges) > 1 else 0
257
+ phi_shifted = (matrix_phi + phi_step) % (2 * np.pi)
258
+
259
+ phi_indices = np.digitize(phi_shifted.ravel(), phi_edges) - 1
260
+ radial_indices = np.digitize(radial_map.ravel(), radial_edges) - 1
261
+
262
+ # Overflow/Underflow handling: put out-of-bounds into first bin
263
+ phi_indices[phi_indices < 0] = 0
264
+ phi_indices[phi_indices >= n_phi_bins] = 0
265
+ radial_indices[mask.ravel()] = 0
266
+
267
+ # --- 6. Binning and Normalization ---
268
+ # Create a signle 1D index for each pixels (phi, radial) combination
269
+ total_bins = n_phi_bins * n_radial_bins
270
+ combined_indices = np.ravel_multi_index((phi_indices, radial_indices), (n_phi_bins, n_radial_bins))
271
+
272
+ indicies_for_norm = combined_indices.copy()
273
+ indicies_for_norm[mask.ravel()] = 0 # Masked pixels go to first bin
274
+ pixel_counts = np.bincount(indicies_for_norm, minlength=total_bins)
275
+ norm_map = np.reshape(pixel_counts, (n_phi_bins, n_radial_bins))
276
+
277
+ # Prep data for intensity summation, excluding masked and thresholded pixels
278
+ final_mask = mask.ravel() | threshold_mask.ravel()
279
+ valid_pixels = ~final_mask
280
+
281
+ valid_indices = combined_indices[valid_pixels]
282
+ valid_img = img.ravel()[valid_pixels]
283
+ valid_correction = correction.ravel()[valid_pixels]
284
+
285
+ # Calculate the sum of corrected intensities in each bin
286
+ summed_intensity = np.bincount(
287
+ valid_indices,
288
+ weights=valid_img / valid_correction,
289
+ minlength=total_bins,
290
+ )
291
+ intensity_map = np.reshape(summed_intensity, (n_phi_bins, n_radial_bins))
292
+
293
+ # Calculate the final azimuthal average
294
+ with np.errstate(invalid='ignore', divide='ignore'):
295
+ azimuthal_average = intensity_map / norm_map
296
+
297
+ return np.squeeze(radial_centers), np.squeeze(azimuthal_average)
298
+
299
+ def keV2Angstroms(keV):
300
+ """
301
+ Convert photon energy from keV to wavelength in Angstroms.
302
+
303
+ Parameters
304
+ ----------
305
+ keV : float
306
+ Photon energy in kilo-electron volts.
307
+
308
+ Returns
309
+ -------
310
+ float
311
+ Corresponding wavelength in Angstroms.
312
+
313
+ Notes
314
+ -----
315
+ Uses the relation λ(Å) = 12.39841984 / E(keV).
316
+ """
317
+ return 12.39841984/keV
318
+
319
+ def Angstroms2keV(angstroms):
320
+ """
321
+ Convert wavelength in Angstroms to photon energy in keV.
322
+
323
+ Parameters
324
+ ----------
325
+ angstroms : float
326
+ Wavelength in Angstroms.
327
+
328
+ Returns
329
+ -------
330
+ float
331
+ Photon energy in kilo-electron volts.
332
+
333
+ Notes
334
+ -----
335
+ Uses the relation E(keV) = 12.39841984 / λ(Å).
336
+ """
337
+ return 12.39841984/angstroms
338
+
339
+ def q2theta(q, keV):
340
+ """
341
+ Convert momentum transfer q to scattering angle theta in radians.
342
+
343
+ Parameters
344
+ ----------
345
+ q : float or array-like
346
+ Momentum transfer in inverse Angstroms (Å⁻¹).
347
+ keV : float
348
+ Photon energy in keV.
349
+
350
+ Returns
351
+ -------
352
+ float or array-like
353
+ Scattering angle θ in radians.
354
+
355
+ Notes
356
+ -----
357
+ Uses the relation θ = 2 * arcsin(q * λ / (4π)), where λ is the photon
358
+ wavelength corresponding to the given energy.
359
+ """
360
+ return 2 * np.arcsin(q * keV2Angstroms(keV) / (4 * np.pi))
361
+
362
+ def theta2q(theta, keV):
363
+ """
364
+ Convert scattering angle theta in radians to momentum transfer q.
365
+
366
+ Parameters
367
+ ----------
368
+ theta : float or array-like
369
+ Scattering angle in radians.
370
+ keV : float
371
+ Photon energy in keV.
372
+
373
+ Returns
374
+ -------
375
+ float or array-like
376
+ Momentum transfer q in inverse Angstroms (Å⁻¹).
377
+
378
+ Notes
379
+ -----
380
+ Uses the relation q = (4π / λ) * sin(θ / 2), where λ is the photon wavelength
381
+ corresponding to the given energy.
382
+ """
383
+ return 4 * np.pi / keV2Angstroms(keV) * np.sin(theta / 2)
384
+
385
+ ELEMENT_NUMBERS = {
386
+ "H": 1, "He": 2, "Li": 3, "Be": 4, "B": 5,
387
+ "C": 6, "N": 7, "O": 8, "F": 9, "Ne": 10,
388
+ "Na": 11, "Mg": 12, "Al": 13, "Si": 14, "P": 15,
389
+ "S": 16, "Cl": 17, "Ar": 18, "K": 19, "Ca": 20,
390
+ "Sc": 21, "Ti": 22, "V": 23, "Cr": 24, "Mn": 25,
391
+ "Fe": 26, "Co": 27, "Ni": 28, "Cu": 29, "Zn": 30,
392
+ "Ga": 31, "Ge": 32, "As": 33, "Se": 34, "Br": 35,
393
+ "Kr": 36, "Rb": 37, "Sr": 38, "Y": 39, "Zr": 40,
394
+ "Nb": 41, "Mo": 42, "Tc": 43, "Ru": 44, "Rh": 45,
395
+ "Pd": 46, "Ag": 47, "Cd": 48, "In": 49, "Sn": 50,
396
+ "Sb": 51, "Te": 52, "I": 53, "Xe": 54, "Cs": 55,
397
+ "Ba": 56, "La": 57, "Ce": 58, "Pr": 59, "Nd": 60,
398
+ "Pm": 61, "Sm": 62, "Eu": 63, "Gd": 64, "Tb": 65,
399
+ "Dy": 66, "Ho": 67, "Er": 68, "Tm": 69, "Yb": 70,
400
+ "Lu": 71, "Hf": 72, "Ta": 73, "W": 74, "Re": 75,
401
+ "Os": 76, "Ir": 77, "Pt": 78, "Au": 79, "Hg": 80,
402
+ "Tl": 81, "Pb": 82, "Bi": 83, "Po": 84, "At": 85,
403
+ "Rn": 86, "Fr": 87, "Ra": 88, "Ac": 89, "Th": 90,
404
+ "Pa": 91, "U": 92, "Np": 93, "Pu": 94, "Am": 95,
405
+ "Cm": 96, "Bk": 97, "Cf": 98, "Es": 99, "Fm": 100,
406
+ "Md": 101, "No": 102, "Lr": 103, "Rf": 104, "Db": 105,
407
+ "Sg": 106, "Bh": 107, "Hs": 108, "Mt": 109, "Ds": 110,
408
+ "Rg": 111, "Cn": 112, "Nh": 113, "Fl": 114, "Mc": 115,
409
+ "Lv": 116, "Ts": 117, "Og": 118
410
+ }
411
+
412
+ ELEMENT_SYMBOLS = {v: k for k, v in ELEMENT_NUMBERS.items()}
413
+
414
+
415
+ def element_symbol_to_number(symbol: str) -> int:
416
+ """
417
+ Convert an element symbol (e.g. 'O') to its atomic number (e.g. 8).
418
+
419
+ Parameters
420
+ ----------
421
+ symbol : str
422
+ The element symbol, case-sensitive (e.g. 'H', 'He', 'Fe').
423
+
424
+ Returns
425
+ -------
426
+ int
427
+ Atomic number of the element.
428
+
429
+ Raises
430
+ ------
431
+ KeyError
432
+ If the symbol is not valid.
433
+ """
434
+ return ELEMENT_NUMBERS[symbol]
435
+
436
+
437
+ def element_number_to_symbol(number: int) -> str:
438
+ """
439
+ Convert an atomic number (e.g. 8) to its element symbol (e.g. 'O').
440
+
441
+ Parameters
442
+ ----------
443
+ number : int
444
+ The atomic number (1 to 118).
445
+
446
+ Returns
447
+ -------
448
+ str
449
+ Element symbol.
450
+
451
+ Raises
452
+ ------
453
+ KeyError
454
+ If the atomic number is not valid.
455
+ """
456
+ return ELEMENT_SYMBOLS[number]
@@ -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,18 @@
1
+ xrayscatteringtools/__init__.py,sha256=LSeycYuFQF7RB0_NIyxhHbeF86ncE22TD9VLroRmPnU,62
2
+ xrayscatteringtools/epicsArch.py,sha256=mdFs-TviBf8JGAFEuxwE49c3dEb2dayZtmICy_uUJEQ,13140
3
+ xrayscatteringtools/io.py,sha256=hE89nXvNK0235t5KYRhJ1uhDfgvw-piHbfuvDSTne3k,11067
4
+ xrayscatteringtools/plotting.py,sha256=uV48_MTrFq1KOtwSyggLKfDclHcRw4GpK9xOOBzazlw,2986
5
+ xrayscatteringtools/utils.py,sha256=6L6aWI4ML2qA7ESOm8pksmIqB7CNMKJtzaBgDTQ5pUU,16271
6
+ xrayscatteringtools/calib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ xrayscatteringtools/calib/geometry_calibration.py,sha256=Zgkj0V3vfeBj9YheL-cB9AoCvDub-tIfBlCb6SpwFIA,7650
8
+ xrayscatteringtools/calib/scattering_corrections.py,sha256=oXty94oiJ8HRw5s7PmR1W19w49ANpgy91rx9oKZom3I,19091
9
+ xrayscatteringtools/theory/Compton_Factors.npy,sha256=kuWFKAghH4ivP4uUbzbwZbf182yb5Y0U2RvqxW_QtkA,6728
10
+ xrayscatteringtools/theory/Scattering_Factors.npy,sha256=A_iYxvLrrGKruwOvtOWCLIc8b_iG-FSkPce5OrFPN_I,4681
11
+ xrayscatteringtools/theory/__init__.py,sha256=o0bQi18T1i2F9EBNYC1dRS8Bx2MvacVXsEZ-c1oHGuk,78
12
+ xrayscatteringtools/theory/iam.py,sha256=RUNwVkpwkTeuJwhalHpSYuMQPm8zcJCehGB3DPzGxzw,9406
13
+ xrayscatteringtools/theory/patterns.py,sha256=Jd6qA9MifqijClKvtWDd4Kp3w8FbOFhw4p8FfaqfGkM,1175
14
+ xrayscatteringtools/theory/data/sf6.h5,sha256=qzMffm4sCN1N0f7BWXWfmnFM0I6DzIy8K2PI6j6epzQ,6048
15
+ xrayscatteringtools-0.0.1.dist-info/METADATA,sha256=JtBKDkKgYCg6BrtD6-GvuSHY5cyuBAiLis29eO1fcYk,2176
16
+ xrayscatteringtools-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ xrayscatteringtools-0.0.1.dist-info/licenses/LICENSE,sha256=HAWdYNAScy8pUxw8FKQ9z6y-b0P8JIfm1cRR7SNE0ls,1069
18
+ xrayscatteringtools-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -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.