nxs-analysis-tools 0.0.41__tar.gz → 0.0.43__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.
Potentially problematic release.
This version of nxs-analysis-tools might be problematic. Click here for more details.
- {nxs_analysis_tools-0.0.41/src/nxs_analysis_tools.egg-info → nxs_analysis_tools-0.0.43}/PKG-INFO +2 -2
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/pyproject.toml +1 -1
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/_meta/__init__.py +1 -1
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/chess.py +13 -2
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/datareduction.py +9 -7
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/pairdistribution.py +58 -14
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43/src/nxs_analysis_tools.egg-info}/PKG-INFO +2 -2
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools.egg-info/SOURCES.txt +3 -1
- nxs_analysis_tools-0.0.43/tests/test_mask_plotting.py +388 -0
- nxs_analysis_tools-0.0.43/tests/test_plot_slice_with_ndarray.py +277 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/LICENSE +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/MANIFEST.in +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/README.md +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/setup.cfg +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/setup.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/__init__.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/fitting.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools.egg-info/dependency_links.txt +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools.egg-info/requires.txt +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools.egg-info/top_level.txt +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_chess.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_chess_fitting.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_datareduction.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_fitting.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_lmfit.py +0 -0
- {nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/tests/test_pairdistribution.py +0 -0
{nxs_analysis_tools-0.0.41/src/nxs_analysis_tools.egg-info → nxs_analysis_tools-0.0.43}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: nxs-analysis-tools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.43
|
|
4
4
|
Summary: Reduce and transform nexus format (.nxs) scattering data.
|
|
5
5
|
Author-email: "Steven J. Gomez Alvarado" <stevenjgomez@ucsb.edu>
|
|
6
6
|
License: MIT License
|
|
@@ -8,6 +8,7 @@ import re
|
|
|
8
8
|
|
|
9
9
|
import matplotlib.pyplot as plt
|
|
10
10
|
import matplotlib as mpl
|
|
11
|
+
import pandas as pd
|
|
11
12
|
import numpy as np
|
|
12
13
|
from IPython.display import display, Markdown
|
|
13
14
|
from nxs_analysis_tools import load_data, Scissors
|
|
@@ -190,14 +191,24 @@ class TempDependence:
|
|
|
190
191
|
|
|
191
192
|
# Convert all temperatures to int temporarily to sort temperatures list before loading
|
|
192
193
|
self.temperatures = [int(t) for t in self.temperatures]
|
|
193
|
-
|
|
194
|
+
|
|
195
|
+
loading_template = pd.DataFrame({'temperature': self.temperatures, 'filename': items_to_load})
|
|
196
|
+
loading_template = loading_template.sort_values(by='temperature')
|
|
197
|
+
self.temperatures = loading_template['temperature']
|
|
194
198
|
self.temperatures = [str(t) for t in self.temperatures]
|
|
199
|
+
items_to_load = loading_template['filename'].to_list()
|
|
195
200
|
|
|
196
201
|
for i, item in enumerate(items_to_load):
|
|
197
202
|
path = os.path.join(self.sample_directory, item)
|
|
198
203
|
|
|
199
204
|
# Save dataset
|
|
200
|
-
|
|
205
|
+
try:
|
|
206
|
+
self.datasets[self.temperatures[i]] = load_transform(path)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
# Report temperature that was unable to load, then raise exception.
|
|
209
|
+
temp_failed = self.temperatures[i]
|
|
210
|
+
print(f"Failed to load data for temperature {temp_failed} K from file {item}. Error: {e}")
|
|
211
|
+
raise # Re-raise the exception
|
|
201
212
|
|
|
202
213
|
# Initialize scissors object
|
|
203
214
|
self.scissors[self.temperatures[i]] = Scissors()
|
{nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/datareduction.py
RENAMED
|
@@ -185,14 +185,14 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
|
185
185
|
"""
|
|
186
186
|
if isinstance(data, np.ndarray):
|
|
187
187
|
if X is None:
|
|
188
|
-
X = NXfield(np.linspace(0, data.shape[
|
|
188
|
+
X = NXfield(np.linspace(0, data.shape[0], data.shape[0]), name='x')
|
|
189
189
|
if Y is None:
|
|
190
|
-
Y = NXfield(np.linspace(0, data.shape[
|
|
190
|
+
Y = NXfield(np.linspace(0, data.shape[1], data.shape[1]), name='y')
|
|
191
191
|
if transpose:
|
|
192
192
|
X, Y = Y, X
|
|
193
193
|
data = data.transpose()
|
|
194
194
|
data = NXdata(NXfield(data, name='value'), (X, Y))
|
|
195
|
-
data_arr = data
|
|
195
|
+
data_arr = data[data.signal].nxdata.transpose()
|
|
196
196
|
elif isinstance(data, (NXdata, NXfield)):
|
|
197
197
|
if X is None:
|
|
198
198
|
X = data[data.axes[0]]
|
|
@@ -787,7 +787,8 @@ def rotate_data(data, lattice_angle, rotation_angle, rotation_axis, printout=Fal
|
|
|
787
787
|
|
|
788
788
|
p = Padder(sliced_data)
|
|
789
789
|
padding = tuple(len(sliced_data[axis]) for axis in sliced_data.axes)
|
|
790
|
-
counts = p.pad(padding)
|
|
790
|
+
counts = p.pad(padding)
|
|
791
|
+
counts = p.padded[p.padded.signal]
|
|
791
792
|
|
|
792
793
|
counts_skewed = ndimage.affine_transform(counts,
|
|
793
794
|
t.inverted().get_matrix()[:2, :2],
|
|
@@ -848,7 +849,7 @@ def rotate_data(data, lattice_angle, rotation_angle, rotation_axis, printout=Fal
|
|
|
848
849
|
elif rotation_axis == 2:
|
|
849
850
|
output_array[:, :, i] = counts_unpadded
|
|
850
851
|
print('\nDone.')
|
|
851
|
-
return NXdata(NXfield(output_array, name=
|
|
852
|
+
return NXdata(NXfield(output_array, name=p.padded.signal),
|
|
852
853
|
(data[data.axes[0]], data[data.axes[1]], data[data.axes[2]]))
|
|
853
854
|
|
|
854
855
|
|
|
@@ -884,7 +885,8 @@ def rotate_data2D(data, lattice_angle, rotation_angle):
|
|
|
884
885
|
|
|
885
886
|
p = Padder(data)
|
|
886
887
|
padding = tuple(len(data[axis]) for axis in data.axes)
|
|
887
|
-
counts = p.pad(padding)
|
|
888
|
+
counts = p.pad(padding)
|
|
889
|
+
counts = p.padded[p.padded.signal]
|
|
888
890
|
|
|
889
891
|
counts_skewed = ndimage.affine_transform(counts,
|
|
890
892
|
t.inverted().get_matrix()[:2, :2],
|
|
@@ -937,7 +939,7 @@ def rotate_data2D(data, lattice_angle, rotation_angle):
|
|
|
937
939
|
counts_unpadded = p.unpad(counts_unskewed)
|
|
938
940
|
|
|
939
941
|
print('\nDone.')
|
|
940
|
-
return NXdata(NXfield(counts_unpadded, name=
|
|
942
|
+
return NXdata(NXfield(counts_unpadded, name=p.padded.signal),
|
|
941
943
|
(data[data.axes[0]], data[data.axes[1]]))
|
|
942
944
|
|
|
943
945
|
|
{nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools/pairdistribution.py
RENAMED
|
@@ -185,23 +185,58 @@ class Symmetrizer2D:
|
|
|
185
185
|
q1 = data_padded[data.axes[0]]
|
|
186
186
|
q2 = data_padded[data.axes[1]]
|
|
187
187
|
|
|
188
|
-
# Define signal to be symmetrized
|
|
189
|
-
counts = data_padded[data.signal].nxdata
|
|
190
|
-
|
|
191
188
|
# Calculate the angle for each data point
|
|
192
189
|
theta = np.arctan2(q1.reshape((-1, 1)), q2.reshape((1, -1)))
|
|
193
190
|
# Create a boolean array for the range of angles
|
|
194
191
|
symmetrization_mask = np.logical_and(theta >= theta_min * np.pi / 180,
|
|
195
192
|
theta <= theta_max * np.pi / 180)
|
|
196
|
-
self.symmetrization_mask = NXdata(NXfield(p.unpad(symmetrization_mask),
|
|
197
|
-
name='mask'),
|
|
198
|
-
(data[data.axes[0]], data[data.axes[1]])
|
|
199
|
-
)
|
|
200
193
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
# Define signal to be transformed
|
|
195
|
+
counts = symmetrization_mask
|
|
196
|
+
|
|
197
|
+
# Scale and skew counts
|
|
198
|
+
skew_angle_adj = 90 - self.skew_angle
|
|
199
|
+
|
|
200
|
+
scale2 = counts.shape[0] / counts.shape[1]
|
|
201
|
+
counts_unscaled2 = ndimage.affine_transform(counts,
|
|
202
|
+
Affine2D().scale(scale2, 1).inverted().get_matrix()[:2, :2],
|
|
203
|
+
offset=[-(1 - scale2) * counts.shape[
|
|
204
|
+
0] / 2 / scale2, 0],
|
|
205
|
+
order=0,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
scale1 = np.cos(skew_angle_adj * np.pi / 180)
|
|
209
|
+
counts_unscaled1 = ndimage.affine_transform(counts_unscaled2,
|
|
210
|
+
Affine2D().scale(scale1, 1).inverted().get_matrix()[:2, :2],
|
|
211
|
+
offset=[-(1 - scale1) * counts.shape[
|
|
212
|
+
0] / 2 / scale1, 0],
|
|
213
|
+
order=0,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
mask = ndimage.affine_transform(counts_unscaled1,
|
|
217
|
+
t.get_matrix()[:2, :2],
|
|
218
|
+
offset=[-counts.shape[0] / 2
|
|
219
|
+
* np.sin(skew_angle_adj * np.pi / 180), 0],
|
|
220
|
+
order=0,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Convert mask to nxdata
|
|
224
|
+
mask = array_to_nxdata(mask, data_padded)
|
|
225
|
+
|
|
226
|
+
# Save mask for user interaction
|
|
227
|
+
self.symmetrization_mask = p.unpad(mask)
|
|
228
|
+
|
|
229
|
+
# Perform masking
|
|
230
|
+
wedge = mask * data_padded
|
|
231
|
+
|
|
232
|
+
# Save wedge for user interaction
|
|
233
|
+
self.wedge = p.unpad(wedge)
|
|
234
|
+
|
|
235
|
+
# Convert wedge back to array for further transformations
|
|
236
|
+
wedge = wedge[data.signal].nxdata
|
|
237
|
+
|
|
238
|
+
# Define signal to be transformed
|
|
239
|
+
counts = wedge
|
|
205
240
|
|
|
206
241
|
# Scale and skew counts
|
|
207
242
|
skew_angle_adj = 90 - self.skew_angle
|
|
@@ -216,7 +251,7 @@ class Symmetrizer2D:
|
|
|
216
251
|
Affine2D().scale(scale1, 1).get_matrix()[:2, :2],
|
|
217
252
|
offset=[(1 - scale1) * counts.shape[0] / 2, 0],
|
|
218
253
|
order=0,
|
|
219
|
-
)
|
|
254
|
+
)
|
|
220
255
|
|
|
221
256
|
scale2 = counts.shape[0] / counts.shape[1]
|
|
222
257
|
wedge = ndimage.affine_transform(wedge,
|
|
@@ -325,15 +360,24 @@ class Symmetrizer2D:
|
|
|
325
360
|
symm_test = s.symmetrize_2d(data)
|
|
326
361
|
fig, axesarr = plt.subplots(2, 2, figsize=(10, 8))
|
|
327
362
|
axes = axesarr.reshape(-1)
|
|
363
|
+
|
|
364
|
+
# Plot the data
|
|
328
365
|
plot_slice(data, skew_angle=s.skew_angle, ax=axes[0], title='data', **kwargs)
|
|
329
|
-
|
|
366
|
+
|
|
367
|
+
# Filter kwargs to exclude 'vmin' and 'vmax'
|
|
368
|
+
filtered_kwargs = {key: value for key, value in kwargs.items() if key not in ('vmin', 'vmax')}
|
|
369
|
+
# Plot the mask
|
|
370
|
+
plot_slice(s.symmetrization_mask, skew_angle=s.skew_angle, ax=axes[1], title='mask', **filtered_kwargs)
|
|
371
|
+
|
|
372
|
+
# Plot the wedge
|
|
330
373
|
plot_slice(s.wedge, skew_angle=s.skew_angle, ax=axes[2], title='wedge', **kwargs)
|
|
374
|
+
|
|
375
|
+
# Plot the symmetrized data
|
|
331
376
|
plot_slice(symm_test, skew_angle=s.skew_angle, ax=axes[3], title='symmetrized', **kwargs)
|
|
332
377
|
plt.subplots_adjust(wspace=0.4)
|
|
333
378
|
plt.show()
|
|
334
379
|
return fig, axesarr
|
|
335
380
|
|
|
336
|
-
|
|
337
381
|
class Symmetrizer3D:
|
|
338
382
|
"""
|
|
339
383
|
A class to symmetrize 3D datasets by performing sequential 2D symmetrization on
|
{nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43/src/nxs_analysis_tools.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: nxs-analysis-tools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.43
|
|
4
4
|
Summary: Reduce and transform nexus format (.nxs) scattering data.
|
|
5
5
|
Author-email: "Steven J. Gomez Alvarado" <stevenjgomez@ucsb.edu>
|
|
6
6
|
License: MIT License
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import os
|
|
3
|
+
import gc
|
|
4
|
+
import math
|
|
5
|
+
from scipy import ndimage
|
|
6
|
+
import scipy
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
from matplotlib.transforms import Affine2D
|
|
9
|
+
from nexusformat.nexus import nxsave, NXroot, NXentry, NXdata, NXfield
|
|
10
|
+
import numpy as np
|
|
11
|
+
from astropy.convolution import Kernel, convolve_fft
|
|
12
|
+
import pyfftw
|
|
13
|
+
from nxs_analysis_tools import *
|
|
14
|
+
from nxs_analysis_tools.datareduction import Padder, array_to_nxdata
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Tools for generating single crystal pair distribution functions.
|
|
18
|
+
"""
|
|
19
|
+
import time
|
|
20
|
+
import os
|
|
21
|
+
import gc
|
|
22
|
+
import math
|
|
23
|
+
from scipy import ndimage
|
|
24
|
+
import scipy
|
|
25
|
+
import matplotlib.pyplot as plt
|
|
26
|
+
from matplotlib.transforms import Affine2D
|
|
27
|
+
from nexusformat.nexus import nxsave, NXroot, NXentry, NXdata, NXfield
|
|
28
|
+
import numpy as np
|
|
29
|
+
from astropy.convolution import Kernel, convolve_fft
|
|
30
|
+
import pyfftw
|
|
31
|
+
# from .datareduction import plot_slice, reciprocal_lattice_params, Padder, \
|
|
32
|
+
# array_to_nxdata
|
|
33
|
+
|
|
34
|
+
# __all__ = ['Symmetrizer2D', 'Symmetrizer3D', 'Puncher', 'Interpolator',
|
|
35
|
+
# 'fourier_transform_nxdata', 'Gaussian3DKernel', 'DeltaPDF',
|
|
36
|
+
# 'generate_gaussian'
|
|
37
|
+
# ]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Symmetrizer2D:
|
|
41
|
+
"""
|
|
42
|
+
A class for symmetrizing 2D datasets.
|
|
43
|
+
|
|
44
|
+
The `Symmetrizer2D` class provides functionality to apply symmetry
|
|
45
|
+
operations such as rotation and mirroring to 2D datasets.
|
|
46
|
+
|
|
47
|
+
Attributes
|
|
48
|
+
----------
|
|
49
|
+
mirror_axis : int or None
|
|
50
|
+
The axis along which mirroring is performed. Default is None, meaning
|
|
51
|
+
no mirroring is applied.
|
|
52
|
+
symmetrized : NXdata or None
|
|
53
|
+
The symmetrized dataset after applying the symmetrization operations.
|
|
54
|
+
Default is None until symmetrization is performed.
|
|
55
|
+
wedges : NXdata or None
|
|
56
|
+
The wedges extracted from the dataset based on the angular limits.
|
|
57
|
+
Default is None until symmetrization is performed.
|
|
58
|
+
rotations : int or None
|
|
59
|
+
The number of rotations needed to reconstruct the full dataset from
|
|
60
|
+
a single wedge. Default is None until parameters are set.
|
|
61
|
+
transform : Affine2D or None
|
|
62
|
+
The transformation matrix used for skewing and scaling the dataset.
|
|
63
|
+
Default is None until parameters are set.
|
|
64
|
+
mirror : bool or None
|
|
65
|
+
Indicates whether mirroring is performed during symmetrization.
|
|
66
|
+
Default is None until parameters are set.
|
|
67
|
+
skew_angle : float or None
|
|
68
|
+
The skew angle (in degrees) between the principal axes of the plane
|
|
69
|
+
to be symmetrized. Default is None until parameters are set.
|
|
70
|
+
theta_max : float or None
|
|
71
|
+
The maximum angle (in degrees) for symmetrization. Default is None
|
|
72
|
+
until parameters are set.
|
|
73
|
+
theta_min : float or None
|
|
74
|
+
The minimum angle (in degrees) for symmetrization. Default is None
|
|
75
|
+
until parameters are set.
|
|
76
|
+
wedge : NXdata or None
|
|
77
|
+
The dataset wedge used in the symmetrization process. Default is
|
|
78
|
+
None until symmetrization is performed.
|
|
79
|
+
symmetrization_mask : NXdata or None
|
|
80
|
+
The mask used for selecting the region of the dataset to be symmetrized.
|
|
81
|
+
Default is None until symmetrization is performed.
|
|
82
|
+
|
|
83
|
+
Methods
|
|
84
|
+
-------
|
|
85
|
+
__init__(**kwargs):
|
|
86
|
+
Initializes the Symmetrizer2D object and optionally sets the parameters
|
|
87
|
+
using `set_parameters`.
|
|
88
|
+
set_parameters(theta_min, theta_max, lattice_angle=90, mirror=True, mirror_axis=0):
|
|
89
|
+
Sets the parameters for the symmetrization operation, including angle limits,
|
|
90
|
+
lattice angle, and mirroring options.
|
|
91
|
+
symmetrize_2d(data):
|
|
92
|
+
Symmetrizes a 2D dataset based on the set parameters.
|
|
93
|
+
test(data, **kwargs):
|
|
94
|
+
Performs a test visualization of the symmetrization process, displaying the
|
|
95
|
+
original data, mask, wedge, and symmetrized result.
|
|
96
|
+
"""
|
|
97
|
+
symmetrization_mask: NXdata
|
|
98
|
+
|
|
99
|
+
def __init__(self, **kwargs):
|
|
100
|
+
"""
|
|
101
|
+
Initializes the Symmetrizer2D object.
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
**kwargs : dict, optional
|
|
106
|
+
Keyword arguments that can be passed to the `set_parameters` method to
|
|
107
|
+
set the symmetrization parameters during initialization.
|
|
108
|
+
"""
|
|
109
|
+
self.mirror_axis = None
|
|
110
|
+
self.symmetrized = None
|
|
111
|
+
self.wedges = None
|
|
112
|
+
self.rotations = None
|
|
113
|
+
self.transform = None
|
|
114
|
+
self.mirror = None
|
|
115
|
+
self.skew_angle = None
|
|
116
|
+
self.theta_max = None
|
|
117
|
+
self.theta_min = None
|
|
118
|
+
self.wedge = None
|
|
119
|
+
if kwargs:
|
|
120
|
+
self.set_parameters(**kwargs)
|
|
121
|
+
|
|
122
|
+
def set_parameters(self, theta_min, theta_max, lattice_angle=90, mirror=True, mirror_axis=0):
|
|
123
|
+
"""
|
|
124
|
+
Sets the parameters for the symmetrization operation, and calculates the
|
|
125
|
+
required transformations and rotations.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
theta_min : float
|
|
130
|
+
The minimum angle in degrees for symmetrization.
|
|
131
|
+
theta_max : float
|
|
132
|
+
The maximum angle in degrees for symmetrization.
|
|
133
|
+
lattice_angle : float, optional
|
|
134
|
+
The angle in degrees between the two principal axes of the plane to be
|
|
135
|
+
symmetrized (default: 90).
|
|
136
|
+
mirror : bool, optional
|
|
137
|
+
If True, perform mirroring during symmetrization (default: True).
|
|
138
|
+
mirror_axis : int, optional
|
|
139
|
+
The axis along which to perform mirroring (default: 0).
|
|
140
|
+
"""
|
|
141
|
+
self.theta_min = theta_min
|
|
142
|
+
self.theta_max = theta_max
|
|
143
|
+
self.skew_angle = lattice_angle
|
|
144
|
+
self.mirror = mirror
|
|
145
|
+
self.mirror_axis = mirror_axis
|
|
146
|
+
|
|
147
|
+
# Define Transformation
|
|
148
|
+
skew_angle_adj = 90 - lattice_angle
|
|
149
|
+
t = Affine2D()
|
|
150
|
+
# Scale y-axis to preserve norm while shearing
|
|
151
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180))
|
|
152
|
+
# Shear along x-axis
|
|
153
|
+
t += Affine2D().skew_deg(skew_angle_adj, 0)
|
|
154
|
+
# Return to original y-axis scaling
|
|
155
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
156
|
+
self.transform = t
|
|
157
|
+
|
|
158
|
+
# Calculate number of rotations needed to reconstruct the dataset
|
|
159
|
+
if mirror:
|
|
160
|
+
rotations = abs(int(360 / (theta_max - theta_min) / 2))
|
|
161
|
+
else:
|
|
162
|
+
rotations = abs(int(360 / (theta_max - theta_min)))
|
|
163
|
+
self.rotations = rotations
|
|
164
|
+
|
|
165
|
+
self.symmetrization_mask = None
|
|
166
|
+
|
|
167
|
+
self.wedges = None
|
|
168
|
+
|
|
169
|
+
self.symmetrized = None
|
|
170
|
+
|
|
171
|
+
def symmetrize_2d(self, data):
|
|
172
|
+
"""
|
|
173
|
+
Symmetrizes a 2D dataset based on the set parameters, applying padding
|
|
174
|
+
to prevent rotation cutoff and handling overlapping pixels.
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
data : NXdata
|
|
179
|
+
The input 2D dataset to be symmetrized.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
symmetrized : NXdata
|
|
184
|
+
The symmetrized 2D dataset.
|
|
185
|
+
"""
|
|
186
|
+
theta_min = self.theta_min
|
|
187
|
+
theta_max = self.theta_max
|
|
188
|
+
mirror = self.mirror
|
|
189
|
+
mirror_axis = self.mirror_axis
|
|
190
|
+
t = self.transform
|
|
191
|
+
rotations = self.rotations
|
|
192
|
+
|
|
193
|
+
# Pad the dataset so that rotations don't get cutoff if they extend
|
|
194
|
+
# past the extent of the dataset
|
|
195
|
+
p = Padder(data)
|
|
196
|
+
padding = tuple(len(data[axis]) for axis in data.axes)
|
|
197
|
+
data_padded = p.pad(padding)
|
|
198
|
+
|
|
199
|
+
# Define axes that span the plane to be transformed
|
|
200
|
+
q1 = data_padded[data.axes[0]]
|
|
201
|
+
q2 = data_padded[data.axes[1]]
|
|
202
|
+
|
|
203
|
+
# Calculate the angle for each data point
|
|
204
|
+
theta = np.arctan2(q1.reshape((-1, 1)), q2.reshape((1, -1)))
|
|
205
|
+
# Create a boolean array for the range of angles
|
|
206
|
+
symmetrization_mask = np.logical_and(theta >= theta_min * np.pi / 180,
|
|
207
|
+
theta <= theta_max * np.pi / 180)
|
|
208
|
+
|
|
209
|
+
# Define signal to be transformed
|
|
210
|
+
counts = symmetrization_mask
|
|
211
|
+
|
|
212
|
+
# Scale and skew counts
|
|
213
|
+
skew_angle_adj = 90 - self.skew_angle
|
|
214
|
+
counts_skew = ndimage.affine_transform(counts,
|
|
215
|
+
t.get_matrix()[:2, :2],
|
|
216
|
+
offset=[-counts.shape[0] / 2
|
|
217
|
+
* np.sin(skew_angle_adj * np.pi / 180), 0],
|
|
218
|
+
order=0,
|
|
219
|
+
)
|
|
220
|
+
scale1 = np.cos(skew_angle_adj * np.pi / 180)
|
|
221
|
+
mask = ndimage.affine_transform(counts_skew,
|
|
222
|
+
Affine2D().scale(scale1, 1).inverted().get_matrix()[:2, :2],
|
|
223
|
+
offset=[-(1 - scale1) * counts.shape[0] / 2, 0],
|
|
224
|
+
order=0,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
scale2 = counts.shape[0] / counts.shape[1]
|
|
228
|
+
mask = ndimage.affine_transform(mask,
|
|
229
|
+
Affine2D().scale(scale2, 1).inverted().get_matrix()[:2, :2],
|
|
230
|
+
offset=[-(1 - scale2) * counts.shape[0] / 2, 0],
|
|
231
|
+
order=0,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Convert mask to nxdata
|
|
235
|
+
mask = array_to_nxdata(mask, data_padded)
|
|
236
|
+
|
|
237
|
+
# Save mask for user interaction
|
|
238
|
+
self.symmetrization_mask = p.unpad(mask)
|
|
239
|
+
|
|
240
|
+
# Perform masking
|
|
241
|
+
wedge = mask*data_padded
|
|
242
|
+
|
|
243
|
+
# Save wedge for user interaction
|
|
244
|
+
self.wedge = p.unpad(wedge)
|
|
245
|
+
|
|
246
|
+
# Convert wedge back to array for further transformations
|
|
247
|
+
wedge = wedge[data.signal].nxdata
|
|
248
|
+
|
|
249
|
+
# Define signal to be transformed
|
|
250
|
+
counts = wedge
|
|
251
|
+
|
|
252
|
+
# Scale and skew counts
|
|
253
|
+
skew_angle_adj = 90 - self.skew_angle
|
|
254
|
+
counts_skew = ndimage.affine_transform(counts,
|
|
255
|
+
t.inverted().get_matrix()[:2, :2],
|
|
256
|
+
offset=[counts.shape[0] / 2
|
|
257
|
+
* np.sin(skew_angle_adj * np.pi / 180), 0],
|
|
258
|
+
order=0,
|
|
259
|
+
)
|
|
260
|
+
scale1 = np.cos(skew_angle_adj * np.pi / 180)
|
|
261
|
+
wedge = ndimage.affine_transform(counts_skew,
|
|
262
|
+
Affine2D().scale(scale1, 1).get_matrix()[:2, :2],
|
|
263
|
+
offset=[(1 - scale1) * counts.shape[0] / 2, 0],
|
|
264
|
+
order=0,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
scale2 = counts.shape[0] / counts.shape[1]
|
|
268
|
+
wedge = ndimage.affine_transform(wedge,
|
|
269
|
+
Affine2D().scale(scale2, 1).get_matrix()[:2, :2],
|
|
270
|
+
offset=[(1 - scale2) * counts.shape[0] / 2, 0],
|
|
271
|
+
order=0,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
# Reconstruct full dataset from wedge
|
|
275
|
+
reconstructed = np.zeros(counts.shape)
|
|
276
|
+
for _ in range(0, rotations):
|
|
277
|
+
# The following are attempts to combine images with minimal overlapping pixels
|
|
278
|
+
reconstructed += wedge
|
|
279
|
+
# reconstructed = np.where(reconstructed == 0, reconstructed + wedge, reconstructed)
|
|
280
|
+
|
|
281
|
+
wedge = ndimage.rotate(wedge, 360 / rotations, reshape=False, order=0)
|
|
282
|
+
|
|
283
|
+
# self.rotated_only = NXdata(NXfield(reconstructed, name=data.signal),
|
|
284
|
+
# (q1, q2))
|
|
285
|
+
|
|
286
|
+
if mirror:
|
|
287
|
+
# The following are attempts to combine images with minimal overlapping pixels
|
|
288
|
+
reconstructed = np.where(reconstructed == 0,
|
|
289
|
+
reconstructed + np.flip(reconstructed, axis=mirror_axis),
|
|
290
|
+
reconstructed)
|
|
291
|
+
# reconstructed += np.flip(reconstructed, axis=0)
|
|
292
|
+
|
|
293
|
+
# self.rotated_and_mirrored = NXdata(NXfield(reconstructed, name=data.signal),
|
|
294
|
+
# (q1, q2))
|
|
295
|
+
|
|
296
|
+
reconstructed = ndimage.affine_transform(reconstructed,
|
|
297
|
+
Affine2D().scale(
|
|
298
|
+
scale2, 1
|
|
299
|
+
).inverted().get_matrix()[:2, :2],
|
|
300
|
+
offset=[-(1 - scale2) * counts.shape[
|
|
301
|
+
0] / 2 / scale2, 0],
|
|
302
|
+
order=0,
|
|
303
|
+
)
|
|
304
|
+
reconstructed = ndimage.affine_transform(reconstructed,
|
|
305
|
+
Affine2D().scale(
|
|
306
|
+
scale1, 1
|
|
307
|
+
).inverted().get_matrix()[:2, :2],
|
|
308
|
+
offset=[-(1 - scale1) * counts.shape[
|
|
309
|
+
0] / 2 / scale1, 0],
|
|
310
|
+
order=0,
|
|
311
|
+
)
|
|
312
|
+
reconstructed = ndimage.affine_transform(reconstructed,
|
|
313
|
+
t.get_matrix()[:2, :2],
|
|
314
|
+
offset=[(-counts.shape[0] / 2
|
|
315
|
+
* np.sin(skew_angle_adj * np.pi / 180)),
|
|
316
|
+
0],
|
|
317
|
+
order=0,
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
reconstructed_unpadded = p.unpad(reconstructed)
|
|
321
|
+
|
|
322
|
+
# Fix any overlapping pixels by truncating counts to max
|
|
323
|
+
reconstructed_unpadded[reconstructed_unpadded > data[data.signal].nxdata.max()] \
|
|
324
|
+
= data[data.signal].nxdata.max()
|
|
325
|
+
|
|
326
|
+
symmetrized = NXdata(NXfield(reconstructed_unpadded, name=data.signal),
|
|
327
|
+
(data[data.axes[0]],
|
|
328
|
+
data[data.axes[1]]))
|
|
329
|
+
|
|
330
|
+
return symmetrized
|
|
331
|
+
|
|
332
|
+
def test(self, data, **kwargs):
|
|
333
|
+
"""
|
|
334
|
+
Performs a test visualization of the symmetrization process to help assess
|
|
335
|
+
the effect of the parameters.
|
|
336
|
+
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
data : ndarray
|
|
340
|
+
The input 2D dataset to be used for the test visualization.
|
|
341
|
+
**kwargs : dict
|
|
342
|
+
Additional keyword arguments to be passed to the plot_slice function.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
fig : Figure
|
|
347
|
+
The matplotlib Figure object that contains the test visualization plot.
|
|
348
|
+
axesarr : ndarray
|
|
349
|
+
The numpy array of Axes objects representing the subplots in the test
|
|
350
|
+
visualization.
|
|
351
|
+
|
|
352
|
+
Notes
|
|
353
|
+
-----
|
|
354
|
+
This method uses the `symmetrize_2d` method to perform the symmetrization on
|
|
355
|
+
the input data and visualize the process.
|
|
356
|
+
|
|
357
|
+
The test visualization plot includes the following subplots:
|
|
358
|
+
- Subplot 1: The original dataset.
|
|
359
|
+
- Subplot 2: The symmetrization mask.
|
|
360
|
+
- Subplot 3: The wedge slice used for reconstruction of the full symmetrized dataset.
|
|
361
|
+
- Subplot 4: The symmetrized dataset.
|
|
362
|
+
|
|
363
|
+
Example usage:
|
|
364
|
+
```
|
|
365
|
+
s = Symmetrizer2D()
|
|
366
|
+
s.set_parameters(theta_min, theta_max, skew_angle, mirror)
|
|
367
|
+
s.test(data)
|
|
368
|
+
```
|
|
369
|
+
"""
|
|
370
|
+
s = self
|
|
371
|
+
symm_test = s.symmetrize_2d(data)
|
|
372
|
+
fig, axesarr = plt.subplots(2, 2, figsize=(10, 8))
|
|
373
|
+
axes = axesarr.reshape(-1)
|
|
374
|
+
plot_slice(data, skew_angle=s.skew_angle, ax=axes[0], title='data', **kwargs)
|
|
375
|
+
plot_slice(s.symmetrization_mask, skew_angle=s.skew_angle, ax=axes[1], title='mask')
|
|
376
|
+
plot_slice(s.wedge, skew_angle=s.skew_angle, ax=axes[2], title='wedge', **kwargs)
|
|
377
|
+
plot_slice(symm_test, skew_angle=s.skew_angle, ax=axes[3], title='symmetrized', **kwargs)
|
|
378
|
+
plt.subplots_adjust(wspace=0.4)
|
|
379
|
+
plt.show()
|
|
380
|
+
return fig, axesarr
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
data = load_transform(r'K:\wilson-3947-a\nxrefine\LaCd3P3\MLA1\LaCd3P3_300.nxs')[:,:,7.9:8.1]
|
|
384
|
+
data = rotate_data(data, lattice_angle=60, rotation_angle=120, rotation_axis=2, printout=True)
|
|
385
|
+
|
|
386
|
+
# from nxs_analysis_tools.pairdistribution import Symmetrizer2D
|
|
387
|
+
s2d = Symmetrizer2D(theta_min=-90, theta_max=-90+60, mirror=True, lattice_angle=60, mirror_axis=1)
|
|
388
|
+
s2d.test(data[:,:,8.0], vmin=0, vmax=100, xlim=(-3,2))
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
from nxs_analysis_tools import *
|
|
2
|
+
from nxs_analysis_tools.datareduction import load_transform
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import numpy as np
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
from matplotlib.transforms import Affine2D
|
|
8
|
+
from matplotlib.markers import MarkerStyle
|
|
9
|
+
from matplotlib.ticker import MultipleLocator
|
|
10
|
+
from matplotlib import colors
|
|
11
|
+
from matplotlib import patches
|
|
12
|
+
from IPython.display import display, Markdown
|
|
13
|
+
from nexusformat.nexus import NXfield, NXdata, nxload, NeXusError, NXroot, NXentry, nxsave
|
|
14
|
+
from scipy import ndimage
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
18
|
+
# skew_angle=90, ax=None, xlim=None, ylim=None,
|
|
19
|
+
# xticks=None, yticks=None, cbar=True, logscale=False,
|
|
20
|
+
# symlogscale=False, cmap='viridis', linthresh=1,
|
|
21
|
+
# title=None, mdheading=None, cbartitle=None,
|
|
22
|
+
# **kwargs):
|
|
23
|
+
# """
|
|
24
|
+
# Plot a 2D slice of the provided dataset, with optional transformations
|
|
25
|
+
# and customizations.
|
|
26
|
+
#
|
|
27
|
+
# Parameters
|
|
28
|
+
# ----------
|
|
29
|
+
# data : :class:`nexusformat.nexus.NXdata` or ndarray
|
|
30
|
+
# The dataset to plot. Can be an `NXdata` object or a `numpy` array.
|
|
31
|
+
#
|
|
32
|
+
# X : NXfield, optional
|
|
33
|
+
# The X axis values. If None, a default range from 0 to the number of
|
|
34
|
+
# columns in `data` is used.
|
|
35
|
+
#
|
|
36
|
+
# Y : NXfield, optional
|
|
37
|
+
# The Y axis values. If None, a default range from 0 to the number of
|
|
38
|
+
# rows in `data` is used.
|
|
39
|
+
#
|
|
40
|
+
# transpose : bool, optional
|
|
41
|
+
# If True, transpose the dataset and its axes before plotting.
|
|
42
|
+
# Default is False.
|
|
43
|
+
#
|
|
44
|
+
# vmin : float, optional
|
|
45
|
+
# The minimum value for the color scale. If not provided, the minimum
|
|
46
|
+
# value of the dataset is used.
|
|
47
|
+
#
|
|
48
|
+
# vmax : float, optional
|
|
49
|
+
# The maximum value for the color scale. If not provided, the maximum
|
|
50
|
+
# value of the dataset is used.
|
|
51
|
+
#
|
|
52
|
+
# skew_angle : float, optional
|
|
53
|
+
# The angle in degrees to shear the plot. Default is 90 degrees (no skew).
|
|
54
|
+
#
|
|
55
|
+
# ax : matplotlib.axes.Axes, optional
|
|
56
|
+
# The `matplotlib` axis to plot on. If None, a new figure and axis will
|
|
57
|
+
# be created.
|
|
58
|
+
#
|
|
59
|
+
# xlim : tuple, optional
|
|
60
|
+
# The limits for the x-axis. If None, the limits are set automatically
|
|
61
|
+
# based on the data.
|
|
62
|
+
#
|
|
63
|
+
# ylim : tuple, optional
|
|
64
|
+
# The limits for the y-axis. If None, the limits are set automatically
|
|
65
|
+
# based on the data.
|
|
66
|
+
#
|
|
67
|
+
# xticks : float or list of float, optional
|
|
68
|
+
# The major tick interval or specific tick locations for the x-axis.
|
|
69
|
+
# Default is to use a minor tick interval of 1.
|
|
70
|
+
#
|
|
71
|
+
# yticks : float or list of float, optional
|
|
72
|
+
# The major tick interval or specific tick locations for the y-axis.
|
|
73
|
+
# Default is to use a minor tick interval of 1.
|
|
74
|
+
#
|
|
75
|
+
# cbar : bool, optional
|
|
76
|
+
# Whether to include a colorbar. Default is True.
|
|
77
|
+
#
|
|
78
|
+
# logscale : bool, optional
|
|
79
|
+
# Whether to use a logarithmic color scale. Default is False.
|
|
80
|
+
#
|
|
81
|
+
# symlogscale : bool, optional
|
|
82
|
+
# Whether to use a symmetrical logarithmic color scale. Default is False.
|
|
83
|
+
#
|
|
84
|
+
# cmap : str or Colormap, optional
|
|
85
|
+
# The colormap to use for the plot. Default is 'viridis'.
|
|
86
|
+
#
|
|
87
|
+
# linthresh : float, optional
|
|
88
|
+
# The linear threshold for symmetrical logarithmic scaling. Default is 1.
|
|
89
|
+
#
|
|
90
|
+
# title : str, optional
|
|
91
|
+
# The title for the plot. If None, no title is set.
|
|
92
|
+
#
|
|
93
|
+
# mdheading : str, optional
|
|
94
|
+
# A Markdown heading to display above the plot. If 'None' or not provided,
|
|
95
|
+
# no heading is displayed.
|
|
96
|
+
#
|
|
97
|
+
# cbartitle : str, optional
|
|
98
|
+
# The title for the colorbar. If None, the colorbar label will be set to
|
|
99
|
+
# the name of the signal.
|
|
100
|
+
#
|
|
101
|
+
# **kwargs
|
|
102
|
+
# Additional keyword arguments passed to `pcolormesh`.
|
|
103
|
+
#
|
|
104
|
+
# Returns
|
|
105
|
+
# -------
|
|
106
|
+
# p : :class:`matplotlib.collections.QuadMesh`
|
|
107
|
+
# The `matplotlib` QuadMesh object representing the plotted data.
|
|
108
|
+
# """
|
|
109
|
+
# if isinstance(data, np.ndarray):
|
|
110
|
+
# if X is None:
|
|
111
|
+
# X = NXfield(np.linspace(0, data.shape[1], data.shape[1]), name='x')
|
|
112
|
+
# if Y is None:
|
|
113
|
+
# Y = NXfield(np.linspace(0, data.shape[0], data.shape[0]), name='y')
|
|
114
|
+
# if transpose:
|
|
115
|
+
# X, Y = Y, X
|
|
116
|
+
# data = data.transpose()
|
|
117
|
+
# data = NXdata(NXfield(data, name='value'), (X, Y))
|
|
118
|
+
# data_arr = data
|
|
119
|
+
# elif isinstance(data, (NXdata, NXfield)):
|
|
120
|
+
# if X is None:
|
|
121
|
+
# X = data[data.axes[0]]
|
|
122
|
+
# if Y is None:
|
|
123
|
+
# Y = data[data.axes[1]]
|
|
124
|
+
# if transpose:
|
|
125
|
+
# X, Y = Y, X
|
|
126
|
+
# data = data.transpose()
|
|
127
|
+
# data_arr = data[data.signal].nxdata.transpose()
|
|
128
|
+
# else:
|
|
129
|
+
# raise TypeError(f"Unexpected data type: {type(data)}. "
|
|
130
|
+
# f"Supported types are np.ndarray and NXdata.")
|
|
131
|
+
#
|
|
132
|
+
# # Display Markdown heading
|
|
133
|
+
# if mdheading is None:
|
|
134
|
+
# pass
|
|
135
|
+
# elif mdheading == "None":
|
|
136
|
+
# display(Markdown('### Figure'))
|
|
137
|
+
# else:
|
|
138
|
+
# display(Markdown('### Figure - ' + mdheading))
|
|
139
|
+
#
|
|
140
|
+
# # Inherit axes if user provides some
|
|
141
|
+
# if ax is not None:
|
|
142
|
+
# fig = ax.get_figure()
|
|
143
|
+
# # Otherwise set up some default axes
|
|
144
|
+
# else:
|
|
145
|
+
# fig = plt.figure()
|
|
146
|
+
# ax = fig.add_axes([0, 0, 1, 1])
|
|
147
|
+
#
|
|
148
|
+
# # If limits not provided, use extrema
|
|
149
|
+
# if vmin is None:
|
|
150
|
+
# vmin = data_arr.min()
|
|
151
|
+
# if vmax is None:
|
|
152
|
+
# vmax = data_arr.max()
|
|
153
|
+
#
|
|
154
|
+
# # Set norm (linear scale, logscale, or symlogscale)
|
|
155
|
+
# norm = colors.Normalize(vmin=vmin, vmax=vmax) # Default: linear scale
|
|
156
|
+
#
|
|
157
|
+
# if symlogscale:
|
|
158
|
+
# norm = colors.SymLogNorm(linthresh=linthresh, vmin=-1 * vmax, vmax=vmax)
|
|
159
|
+
# elif logscale:
|
|
160
|
+
# norm = colors.LogNorm(vmin=vmin, vmax=vmax)
|
|
161
|
+
#
|
|
162
|
+
# # Plot data
|
|
163
|
+
# p = ax.pcolormesh(X.nxdata, Y.nxdata, data_arr, shading='auto', norm=norm, cmap=cmap, **kwargs)
|
|
164
|
+
#
|
|
165
|
+
# ## Transform data to new coordinate system if necessary
|
|
166
|
+
# # Correct skew angle
|
|
167
|
+
# skew_angle_adj = 90 - skew_angle
|
|
168
|
+
# # Create blank 2D affine transformation
|
|
169
|
+
# t = Affine2D()
|
|
170
|
+
# # Scale y-axis to preserve norm while shearing
|
|
171
|
+
# t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180))
|
|
172
|
+
# # Shear along x-axis
|
|
173
|
+
# t += Affine2D().skew_deg(skew_angle_adj, 0)
|
|
174
|
+
# # Return to original y-axis scaling
|
|
175
|
+
# t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
176
|
+
# ## Correct for x-displacement after shearing
|
|
177
|
+
# # If ylims provided, use those
|
|
178
|
+
# if ylim is not None:
|
|
179
|
+
# # Set ylims
|
|
180
|
+
# ax.set(ylim=ylim)
|
|
181
|
+
# ymin, ymax = ylim
|
|
182
|
+
# # Else, use current ylims
|
|
183
|
+
# else:
|
|
184
|
+
# ymin, ymax = ax.get_ylim()
|
|
185
|
+
# # Use ylims to calculate translation (necessary to display axes in correct position)
|
|
186
|
+
# p.set_transform(t
|
|
187
|
+
# + Affine2D().translate(-ymin * np.sin(skew_angle_adj * np.pi / 180), 0)
|
|
188
|
+
# + ax.transData)
|
|
189
|
+
#
|
|
190
|
+
# # Set x limits
|
|
191
|
+
# if xlim is not None:
|
|
192
|
+
# xmin, xmax = xlim
|
|
193
|
+
# else:
|
|
194
|
+
# xmin, xmax = ax.get_xlim()
|
|
195
|
+
# if skew_angle <= 90:
|
|
196
|
+
# ax.set(xlim=(xmin, xmax + (ymax - ymin) / np.tan((90 - skew_angle_adj) * np.pi / 180)))
|
|
197
|
+
# else:
|
|
198
|
+
# ax.set(xlim=(xmin - (ymax - ymin) / np.tan((skew_angle_adj - 90) * np.pi / 180), xmax))
|
|
199
|
+
#
|
|
200
|
+
# # Correct aspect ratio for the x/y axes after transformation
|
|
201
|
+
# ax.set(aspect=np.cos(skew_angle_adj * np.pi / 180))
|
|
202
|
+
#
|
|
203
|
+
# # Add tick marks all around
|
|
204
|
+
# ax.tick_params(direction='in', top=True, right=True, which='both')
|
|
205
|
+
#
|
|
206
|
+
# # Set tick locations
|
|
207
|
+
# if xticks is None:
|
|
208
|
+
# # Add default minor ticks
|
|
209
|
+
# ax.xaxis.set_minor_locator(MultipleLocator(1))
|
|
210
|
+
# else:
|
|
211
|
+
# # Otherwise use user provided values
|
|
212
|
+
# ax.xaxis.set_major_locator(MultipleLocator(xticks))
|
|
213
|
+
# ax.xaxis.set_minor_locator(MultipleLocator(1))
|
|
214
|
+
# if yticks is None:
|
|
215
|
+
# # Add default minor ticks
|
|
216
|
+
# ax.yaxis.set_minor_locator(MultipleLocator(1))
|
|
217
|
+
# else:
|
|
218
|
+
# # Otherwise use user provided values
|
|
219
|
+
# ax.yaxis.set_major_locator(MultipleLocator(yticks))
|
|
220
|
+
# ax.yaxis.set_minor_locator(MultipleLocator(1))
|
|
221
|
+
#
|
|
222
|
+
# # Apply transform to tick marks
|
|
223
|
+
# for i in range(0, len(ax.xaxis.get_ticklines())):
|
|
224
|
+
# # Tick marker
|
|
225
|
+
# m = MarkerStyle(3)
|
|
226
|
+
# line = ax.xaxis.get_majorticklines()[i]
|
|
227
|
+
# if i % 2:
|
|
228
|
+
# # Top ticks (translation here makes their direction="in")
|
|
229
|
+
# m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
230
|
+
# # This first method shifts the top ticks horizontally to match the skew angle.
|
|
231
|
+
# # This does not look good in all cases.
|
|
232
|
+
# # line.set_transform(Affine2D().translate((ymax-ymin)*np.sin(skew_angle*np.pi/180),0) +
|
|
233
|
+
# # line.get_transform())
|
|
234
|
+
# # This second method skews the tick marks in place and
|
|
235
|
+
# # can sometimes lead to them being misaligned.
|
|
236
|
+
# line.set_transform(line.get_transform()) # This does nothing
|
|
237
|
+
# else:
|
|
238
|
+
# # Bottom ticks
|
|
239
|
+
# m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
240
|
+
#
|
|
241
|
+
# line.set_marker(m)
|
|
242
|
+
#
|
|
243
|
+
# for i in range(0, len(ax.xaxis.get_minorticklines())):
|
|
244
|
+
# m = MarkerStyle(2)
|
|
245
|
+
# line = ax.xaxis.get_minorticklines()[i]
|
|
246
|
+
# if i % 2:
|
|
247
|
+
# m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
248
|
+
# else:
|
|
249
|
+
# m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
250
|
+
#
|
|
251
|
+
# line.set_marker(m)
|
|
252
|
+
#
|
|
253
|
+
# if cbar:
|
|
254
|
+
# colorbar = fig.colorbar(p)
|
|
255
|
+
# if cbartitle is None:
|
|
256
|
+
# colorbar.set_label(data.signal)
|
|
257
|
+
#
|
|
258
|
+
# ax.set(
|
|
259
|
+
# xlabel=X.nxname,
|
|
260
|
+
# ylabel=Y.nxname,
|
|
261
|
+
# )
|
|
262
|
+
#
|
|
263
|
+
# if title is not None:
|
|
264
|
+
# ax.set_title(title)
|
|
265
|
+
#
|
|
266
|
+
# # Return the quadmesh object
|
|
267
|
+
# return p
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
data = load_transform(r'K:\wilson-3947-a\nxrefine\LaCd3P3\MLA1\LaCd3P3_300.nxs')
|
|
271
|
+
|
|
272
|
+
# print(data.tree)
|
|
273
|
+
fig = plt.figure(figsize=(5,3))
|
|
274
|
+
ax = fig.add_axes([0,0,1,1])
|
|
275
|
+
plot_slice(data[-1.0:1.0, -0.5:0.5, 0.0].counts.nxdata, vmin=0, vmax=100, cbar=False, ax=ax)
|
|
276
|
+
fig.tight_layout()
|
|
277
|
+
plt.show()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nxs_analysis_tools-0.0.41 → nxs_analysis_tools-0.0.43}/src/nxs_analysis_tools.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|