nxs-analysis-tools 0.0.46__tar.gz → 0.0.47__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.46/src/nxs_analysis_tools.egg-info → nxs_analysis_tools-0.0.47}/PKG-INFO +1 -1
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/pyproject.toml +1 -1
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/_meta/__init__.py +1 -1
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/datareduction.py +76 -21
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47/src/nxs_analysis_tools.egg-info}/PKG-INFO +1 -1
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools.egg-info/SOURCES.txt +2 -0
- nxs_analysis_tools-0.0.47/tests/test_accurate_highlight.py +388 -0
- nxs_analysis_tools-0.0.47/tests/test_sum_axis.py +299 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/LICENSE +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/MANIFEST.in +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/README.md +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/setup.cfg +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/setup.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/__init__.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/chess.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/fitting.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/pairdistribution.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools.egg-info/dependency_links.txt +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools.egg-info/requires.txt +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools.egg-info/top_level.txt +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_chess.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_chess_fitting.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_datareduction.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_fitting.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_lmfit.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_mask_plotting.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_pairdistribution.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_plot_slice_with_ndarray.py +0 -0
- {nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_symmetrizer_rectangular_plane.py +0 -0
{nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/datareduction.py
RENAMED
|
@@ -16,7 +16,7 @@ from scipy import ndimage
|
|
|
16
16
|
# Specify items on which users are allowed to perform standalone imports
|
|
17
17
|
__all__ = ['load_data', 'load_transform', 'plot_slice', 'Scissors',
|
|
18
18
|
'reciprocal_lattice_params', 'rotate_data', 'rotate_data_2D'
|
|
19
|
-
|
|
19
|
+
'array_to_nxdata', 'Padder']
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def load_data(path, print_tree=True):
|
|
@@ -107,7 +107,7 @@ def array_to_nxdata(array, data_template, signal_name=None):
|
|
|
107
107
|
tuple(d[d.axes[i]] for i in range(len(d.axes))))
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
110
|
+
def plot_slice(data, X=None, Y=None, sum_axis=None, transpose=False, vmin=None, vmax=None,
|
|
111
111
|
skew_angle=90, ax=None, xlim=None, ylim=None,
|
|
112
112
|
xticks=None, yticks=None, cbar=True, logscale=False,
|
|
113
113
|
symlogscale=False, cmap='viridis', linthresh=1,
|
|
@@ -130,6 +130,10 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
|
130
130
|
The Y axis values. If None, a default range from 0 to the number of
|
|
131
131
|
rows in `data` is used.
|
|
132
132
|
|
|
133
|
+
sum_axis : int, optional
|
|
134
|
+
If the input data is 3D, this specifies the axis to sum over in order
|
|
135
|
+
to reduce the data to 2D for plotting. Required if `data` has three dimensions.
|
|
136
|
+
|
|
133
137
|
transpose : bool, optional
|
|
134
138
|
If True, transpose the dataset and its axes before plotting.
|
|
135
139
|
Default is False.
|
|
@@ -199,7 +203,37 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
|
199
203
|
p : :class:`matplotlib.collections.QuadMesh`
|
|
200
204
|
The `matplotlib` QuadMesh object representing the plotted data.
|
|
201
205
|
"""
|
|
206
|
+
is_array = False
|
|
207
|
+
is_nxdata = False
|
|
208
|
+
|
|
202
209
|
if isinstance(data, np.ndarray):
|
|
210
|
+
is_array = True
|
|
211
|
+
elif isinstance(data, (NXdata, NXfield)):
|
|
212
|
+
is_nxdata = True
|
|
213
|
+
else:
|
|
214
|
+
raise TypeError(f"Unexpected data type: {type(data)}. "
|
|
215
|
+
f"Supported types are np.ndarray and NXdata.")
|
|
216
|
+
|
|
217
|
+
# If three-dimensional, demand sum_axis to reduce to two dimensions.
|
|
218
|
+
if is_array and len(data.shape) == 3:
|
|
219
|
+
assert sum_axis is not None, "sum_axis must be specified when data is a 3D array"
|
|
220
|
+
|
|
221
|
+
data = data.sum(axis=sum_axis)
|
|
222
|
+
|
|
223
|
+
if is_nxdata and len(data.shape) == 3:
|
|
224
|
+
assert sum_axis is not None, "sum_axis must be specified when data is a 3D array"
|
|
225
|
+
|
|
226
|
+
arr = data.nxsignal.nxdata
|
|
227
|
+
arr = arr.sum(axis=sum_axis)
|
|
228
|
+
|
|
229
|
+
# Create a 2D template from the original nxdata
|
|
230
|
+
slice_obj = [slice(None)] * len(data.shape)
|
|
231
|
+
slice_obj[sum_axis] = 0
|
|
232
|
+
|
|
233
|
+
# Use the 2D template to create a new nxdata
|
|
234
|
+
data = array_to_nxdata(arr, data[slice_obj])
|
|
235
|
+
|
|
236
|
+
if is_array:
|
|
203
237
|
if X is None:
|
|
204
238
|
X = NXfield(np.linspace(0, data.shape[0], data.shape[0]), name='x')
|
|
205
239
|
if Y is None:
|
|
@@ -209,7 +243,7 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
|
209
243
|
data = data.transpose()
|
|
210
244
|
data = NXdata(NXfield(data, name='value'), (X, Y))
|
|
211
245
|
data_arr = data[data.signal].nxdata.transpose()
|
|
212
|
-
elif
|
|
246
|
+
elif is_nxdata:
|
|
213
247
|
if X is None:
|
|
214
248
|
X = data[data.axes[0]]
|
|
215
249
|
if Y is None:
|
|
@@ -218,9 +252,6 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None,
|
|
|
218
252
|
X, Y = Y, X
|
|
219
253
|
data = data.transpose()
|
|
220
254
|
data_arr = data[data.signal].nxdata.transpose()
|
|
221
|
-
else:
|
|
222
|
-
raise TypeError(f"Unexpected data type: {type(data)}. "
|
|
223
|
-
f"Supported types are np.ndarray and NXdata.")
|
|
224
255
|
|
|
225
256
|
# Display Markdown heading
|
|
226
257
|
if mdheading is None:
|
|
@@ -559,22 +590,31 @@ class Scissors:
|
|
|
559
590
|
|
|
560
591
|
return self.linecut
|
|
561
592
|
|
|
562
|
-
def highlight_integration_window(self, data=None, label=None, highlight_color='red',
|
|
593
|
+
def highlight_integration_window(self, data=None, width=None, height=None, label=None, highlight_color='red',
|
|
594
|
+
**kwargs):
|
|
563
595
|
"""
|
|
564
|
-
Plots integration window highlighted on the three principal cross
|
|
565
|
-
temperature dataset.
|
|
596
|
+
Plots the integration window highlighted on the three principal 2D cross-sections of a 3D dataset.
|
|
566
597
|
|
|
567
598
|
Parameters
|
|
568
599
|
----------
|
|
569
600
|
data : array-like, optional
|
|
570
|
-
The
|
|
571
|
-
|
|
601
|
+
The 3D dataset to visualize. If not provided, uses `self.data`.
|
|
602
|
+
width : float, optional
|
|
603
|
+
Width of the visible x-axis range in each subplot. Used to zoom in on the integration region.
|
|
604
|
+
height : float, optional
|
|
605
|
+
Height of the visible y-axis range in each subplot. Used to zoom in on the integration region.
|
|
572
606
|
label : str, optional
|
|
573
|
-
|
|
607
|
+
Label for the rectangle patch marking the integration window, used in the legend.
|
|
574
608
|
highlight_color : str, optional
|
|
575
|
-
|
|
576
|
-
**kwargs :
|
|
577
|
-
Additional keyword arguments to
|
|
609
|
+
Color of the rectangle edges highlighting the integration window. Default is 'red'.
|
|
610
|
+
**kwargs : dict, optional
|
|
611
|
+
Additional keyword arguments passed to `plot_slice` for customizing the plot (e.g., colormap, vmin, vmax).
|
|
612
|
+
|
|
613
|
+
Returns
|
|
614
|
+
-------
|
|
615
|
+
p1, p2, p3 : matplotlib.collections.QuadMesh
|
|
616
|
+
The plotted QuadMesh objects for the three cross-sections:
|
|
617
|
+
XY at fixed Z, XZ at fixed Y, and YZ at fixed X.
|
|
578
618
|
|
|
579
619
|
"""
|
|
580
620
|
data = self.data if data is None else data
|
|
@@ -584,7 +624,7 @@ class Scissors:
|
|
|
584
624
|
# Create a figure and subplots
|
|
585
625
|
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
|
|
586
626
|
|
|
587
|
-
# Plot cross
|
|
627
|
+
# Plot cross-section 1
|
|
588
628
|
slice_obj = [slice(None)] * data.ndim
|
|
589
629
|
slice_obj[2] = center[2]
|
|
590
630
|
|
|
@@ -603,7 +643,12 @@ class Scissors:
|
|
|
603
643
|
)
|
|
604
644
|
ax.add_patch(rect_diffuse)
|
|
605
645
|
|
|
606
|
-
|
|
646
|
+
if 'xlim' not in kwargs and width is not None:
|
|
647
|
+
ax.set(xlim=(center[0] - width / 2, center[0] + width / 2))
|
|
648
|
+
if 'ylim' not in kwargs and height is not None:
|
|
649
|
+
ax.set(ylim=(center[1] - height / 2, center[1] + height / 2))
|
|
650
|
+
|
|
651
|
+
# Plot cross-section 2
|
|
607
652
|
slice_obj = [slice(None)] * data.ndim
|
|
608
653
|
slice_obj[1] = center[1]
|
|
609
654
|
|
|
@@ -622,7 +667,12 @@ class Scissors:
|
|
|
622
667
|
)
|
|
623
668
|
ax.add_patch(rect_diffuse)
|
|
624
669
|
|
|
625
|
-
|
|
670
|
+
if 'xlim' not in kwargs and width is not None:
|
|
671
|
+
ax.set(xlim=(center[0] - width / 2, center[0] + width / 2))
|
|
672
|
+
if 'ylim' not in kwargs and height is not None:
|
|
673
|
+
ax.set(ylim=(center[2] - height / 2, center[2] + height / 2))
|
|
674
|
+
|
|
675
|
+
# Plot cross-section 3
|
|
626
676
|
slice_obj = [slice(None)] * data.ndim
|
|
627
677
|
slice_obj[0] = center[0]
|
|
628
678
|
|
|
@@ -641,6 +691,11 @@ class Scissors:
|
|
|
641
691
|
)
|
|
642
692
|
ax.add_patch(rect_diffuse)
|
|
643
693
|
|
|
694
|
+
if 'xlim' not in kwargs and width is not None:
|
|
695
|
+
ax.set(xlim=(center[1] - width / 2, center[1] + width / 2))
|
|
696
|
+
if 'ylim' not in kwargs and height is not None:
|
|
697
|
+
ax.set(ylim=(center[2] - height / 2, center[2] + height / 2))
|
|
698
|
+
|
|
644
699
|
# Adjust subplot padding
|
|
645
700
|
fig.subplots_adjust(wspace=0.5)
|
|
646
701
|
|
|
@@ -665,7 +720,7 @@ class Scissors:
|
|
|
665
720
|
|
|
666
721
|
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
|
|
667
722
|
|
|
668
|
-
# Plot cross
|
|
723
|
+
# Plot cross-section 1
|
|
669
724
|
slice_obj = [slice(None)] * data.ndim
|
|
670
725
|
slice_obj[2] = center[2]
|
|
671
726
|
p1 = plot_slice(data[slice_obj],
|
|
@@ -685,7 +740,7 @@ class Scissors:
|
|
|
685
740
|
**kwargs)
|
|
686
741
|
axes[1].set_aspect(len(data[data.axes[0]].nxdata) / len(data[data.axes[2]].nxdata))
|
|
687
742
|
|
|
688
|
-
# Plot cross
|
|
743
|
+
# Plot cross-section 3
|
|
689
744
|
slice_obj = [slice(None)] * data.ndim
|
|
690
745
|
slice_obj[0] = center[0]
|
|
691
746
|
p2 = plot_slice(data[slice_obj],
|
|
@@ -1015,7 +1070,7 @@ class Padder:
|
|
|
1015
1070
|
self.data = data
|
|
1016
1071
|
|
|
1017
1072
|
self.steps = tuple((data[axis].nxdata[1] - data[axis].nxdata[0])
|
|
1018
|
-
|
|
1073
|
+
for axis in data.axes)
|
|
1019
1074
|
|
|
1020
1075
|
# Absolute value of the maximum value; assumes the domain of the input
|
|
1021
1076
|
# is symmetric (eg, -H_min = H_max)
|
{nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools.egg-info/SOURCES.txt
RENAMED
|
@@ -14,6 +14,7 @@ src/nxs_analysis_tools.egg-info/SOURCES.txt
|
|
|
14
14
|
src/nxs_analysis_tools.egg-info/dependency_links.txt
|
|
15
15
|
src/nxs_analysis_tools.egg-info/requires.txt
|
|
16
16
|
src/nxs_analysis_tools.egg-info/top_level.txt
|
|
17
|
+
tests/test_accurate_highlight.py
|
|
17
18
|
tests/test_chess.py
|
|
18
19
|
tests/test_chess_fitting.py
|
|
19
20
|
tests/test_datareduction.py
|
|
@@ -22,4 +23,5 @@ tests/test_lmfit.py
|
|
|
22
23
|
tests/test_mask_plotting.py
|
|
23
24
|
tests/test_pairdistribution.py
|
|
24
25
|
tests/test_plot_slice_with_ndarray.py
|
|
26
|
+
tests/test_sum_axis.py
|
|
25
27
|
tests/test_symmetrizer_rectangular_plane.py
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from matplotlib.transforms import Affine2D
|
|
5
|
+
from matplotlib.markers import MarkerStyle
|
|
6
|
+
from matplotlib.ticker import MultipleLocator
|
|
7
|
+
from matplotlib import colors
|
|
8
|
+
from matplotlib import patches
|
|
9
|
+
from IPython.display import display, Markdown
|
|
10
|
+
from nexusformat.nexus import NXfield, NXdata, nxload, NeXusError, NXroot, NXentry, nxsave
|
|
11
|
+
from scipy import ndimage
|
|
12
|
+
from nxs_analysis_tools.datareduction import plot_slice, load_data
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Scissors:
|
|
16
|
+
"""
|
|
17
|
+
Scissors class provides functionality for reducing data to a 1D linecut using an integration
|
|
18
|
+
window.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
data : :class:`nexusformat.nexus.NXdata` or None
|
|
23
|
+
Input :class:`nexusformat.nexus.NXdata`.
|
|
24
|
+
center : tuple or None
|
|
25
|
+
Central coordinate around which to perform the linecut.
|
|
26
|
+
window : tuple or None
|
|
27
|
+
Extents of the window for integration along each axis.
|
|
28
|
+
axis : int or None
|
|
29
|
+
Axis along which to perform the integration.
|
|
30
|
+
integration_volume : :class:`nexusformat.nexus.NXdata` or None
|
|
31
|
+
Data array after applying the integration window.
|
|
32
|
+
integrated_axes : tuple or None
|
|
33
|
+
Indices of axes that were integrated.
|
|
34
|
+
linecut : :class:`nexusformat.nexus.NXdata` or None
|
|
35
|
+
1D linecut data after integration.
|
|
36
|
+
integration_window : tuple or None
|
|
37
|
+
Slice object representing the integration window in the data array.
|
|
38
|
+
|
|
39
|
+
Methods
|
|
40
|
+
-------
|
|
41
|
+
set_data(data)
|
|
42
|
+
Set the input :class:`nexusformat.nexus.NXdata`.
|
|
43
|
+
get_data()
|
|
44
|
+
Get the input :class:`nexusformat.nexus.NXdata`.
|
|
45
|
+
set_center(center)
|
|
46
|
+
Set the central coordinate for the linecut.
|
|
47
|
+
set_window(window, axis=None, verbose=False)
|
|
48
|
+
Set the extents of the integration window.
|
|
49
|
+
get_window()
|
|
50
|
+
Get the extents of the integration window.
|
|
51
|
+
cut_data(center=None, window=None, axis=None, verbose=False)
|
|
52
|
+
Reduce data to a 1D linecut using the integration window.
|
|
53
|
+
highlight_integration_window(data=None, label=None, highlight_color='red', **kwargs)
|
|
54
|
+
Plot the integration window highlighted on a 2D heatmap of the full dataset.
|
|
55
|
+
plot_integration_window(**kwargs)
|
|
56
|
+
Plot a 2D heatmap of the integration window data.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def __init__(self, data=None, center=None, window=None, axis=None):
|
|
60
|
+
"""
|
|
61
|
+
Initializes a Scissors object.
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
data : :class:`nexusformat.nexus.NXdata` or None, optional
|
|
66
|
+
Input NXdata. Default is None.
|
|
67
|
+
center : tuple or None, optional
|
|
68
|
+
Central coordinate around which to perform the linecut. Default is None.
|
|
69
|
+
window : tuple or None, optional
|
|
70
|
+
Extents of the window for integration along each axis. Default is None.
|
|
71
|
+
axis : int or None, optional
|
|
72
|
+
Axis along which to perform the integration. Default is None.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
self.data = data
|
|
76
|
+
self.center = tuple(float(i) for i in center) if center is not None else None
|
|
77
|
+
self.window = tuple(float(i) for i in window) if window is not None else None
|
|
78
|
+
self.axis = axis
|
|
79
|
+
|
|
80
|
+
self.integration_volume = None
|
|
81
|
+
self.integrated_axes = None
|
|
82
|
+
self.linecut = None
|
|
83
|
+
self.integration_window = None
|
|
84
|
+
|
|
85
|
+
def set_data(self, data):
|
|
86
|
+
"""
|
|
87
|
+
Set the input NXdata.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
data : :class:`nexusformat.nexus.NXdata`
|
|
92
|
+
Input data array.
|
|
93
|
+
"""
|
|
94
|
+
self.data = data
|
|
95
|
+
|
|
96
|
+
def get_data(self):
|
|
97
|
+
"""
|
|
98
|
+
Get the input data array.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
ndarray or None
|
|
103
|
+
Input data array.
|
|
104
|
+
"""
|
|
105
|
+
return self.data
|
|
106
|
+
|
|
107
|
+
def set_center(self, center):
|
|
108
|
+
"""
|
|
109
|
+
Set the central coordinate for the linecut.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
center : tuple
|
|
114
|
+
Central coordinate around which to perform the linecut.
|
|
115
|
+
"""
|
|
116
|
+
self.center = tuple(float(i) for i in center) if center is not None else None
|
|
117
|
+
|
|
118
|
+
def set_window(self, window, axis=None, verbose=False):
|
|
119
|
+
"""
|
|
120
|
+
Set the extents of the integration window.
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
123
|
+
----------
|
|
124
|
+
window : tuple
|
|
125
|
+
Extents of the window for integration along each axis.
|
|
126
|
+
axis : int or None, optional
|
|
127
|
+
The axis along which to perform the linecut. If not specified, the value from the
|
|
128
|
+
object's attribute will be used.
|
|
129
|
+
verbose : bool, optional
|
|
130
|
+
Enables printout of linecut axis and integrated axes. Default False.
|
|
131
|
+
|
|
132
|
+
"""
|
|
133
|
+
self.window = tuple(float(i) for i in window) if window is not None else None
|
|
134
|
+
|
|
135
|
+
# Determine the axis for integration
|
|
136
|
+
self.axis = window.index(max(window)) if axis is None else axis
|
|
137
|
+
|
|
138
|
+
# Determine the integrated axes (axes other than the integration axis)
|
|
139
|
+
self.integrated_axes = tuple(i for i in range(self.data.ndim) if i != self.axis)
|
|
140
|
+
|
|
141
|
+
if verbose:
|
|
142
|
+
print("Linecut axis: " + str(self.data.axes[self.axis]))
|
|
143
|
+
print("Integrated axes: " + str([self.data.axes[axis]
|
|
144
|
+
for axis in self.integrated_axes]))
|
|
145
|
+
|
|
146
|
+
def get_window(self):
|
|
147
|
+
"""
|
|
148
|
+
Get the extents of the integration window.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
tuple or None
|
|
153
|
+
Extents of the integration window.
|
|
154
|
+
"""
|
|
155
|
+
return self.window
|
|
156
|
+
|
|
157
|
+
def cut_data(self, center=None, window=None, axis=None, verbose=False):
|
|
158
|
+
"""
|
|
159
|
+
Reduces data to a 1D linecut with integration extents specified by the
|
|
160
|
+
window about a central coordinate.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
center : float or None, optional
|
|
165
|
+
Central coordinate for the linecut. If not specified, the value from the object's
|
|
166
|
+
attribute will be used.
|
|
167
|
+
window : tuple or None, optional
|
|
168
|
+
Integration window extents around the central coordinate. If not specified, the value
|
|
169
|
+
from the object's attribute will be used.
|
|
170
|
+
axis : int or None, optional
|
|
171
|
+
The axis along which to perform the linecut. If not specified, the value from the
|
|
172
|
+
object's attribute will be used.
|
|
173
|
+
verbose : bool
|
|
174
|
+
Enables printout of linecut axis and integrated axes. Default False.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
integrated_data : :class:`nexusformat.nexus.NXdata`
|
|
179
|
+
1D linecut data after integration.
|
|
180
|
+
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
# Extract necessary attributes from the object
|
|
184
|
+
data = self.data
|
|
185
|
+
center = center if center is not None else self.center
|
|
186
|
+
self.set_center(center)
|
|
187
|
+
window = window if window is not None else self.window
|
|
188
|
+
self.set_window(window, axis, verbose)
|
|
189
|
+
|
|
190
|
+
# Convert the center to a tuple of floats
|
|
191
|
+
center = tuple(float(c) for c in center)
|
|
192
|
+
|
|
193
|
+
# Calculate the start and stop indices for slicing the data
|
|
194
|
+
start = np.subtract(center, window)
|
|
195
|
+
stop = np.add(center, window)
|
|
196
|
+
slice_obj = tuple(slice(s, e) for s, e in zip(start, stop))
|
|
197
|
+
self.integration_window = slice_obj
|
|
198
|
+
|
|
199
|
+
# Perform the data cut
|
|
200
|
+
self.integration_volume = data[slice_obj]
|
|
201
|
+
self.integration_volume.nxname = data.nxname
|
|
202
|
+
|
|
203
|
+
# Perform integration along the integrated axes
|
|
204
|
+
integrated_data = np.sum(self.integration_volume[self.integration_volume.signal].nxdata,
|
|
205
|
+
axis=self.integrated_axes)
|
|
206
|
+
|
|
207
|
+
# Create an NXdata object for the linecut data
|
|
208
|
+
self.linecut = NXdata(NXfield(integrated_data, name=self.integration_volume.signal),
|
|
209
|
+
self.integration_volume[self.integration_volume.axes[self.axis]])
|
|
210
|
+
self.linecut.nxname = self.integration_volume.nxname
|
|
211
|
+
|
|
212
|
+
return self.linecut
|
|
213
|
+
|
|
214
|
+
def highlight_integration_window(self, data=None, width=None, height=None, label=None, highlight_color='red', **kwargs):
|
|
215
|
+
"""
|
|
216
|
+
Plots the integration window highlighted on the three principal 2D cross-sections of a 3D dataset.
|
|
217
|
+
|
|
218
|
+
Parameters
|
|
219
|
+
----------
|
|
220
|
+
data : array-like, optional
|
|
221
|
+
The 3D dataset to visualize. If not provided, uses `self.data`.
|
|
222
|
+
width : float, optional
|
|
223
|
+
Width of the visible x-axis range in each subplot. Used to zoom in on the integration region.
|
|
224
|
+
height : float, optional
|
|
225
|
+
Height of the visible y-axis range in each subplot. Used to zoom in on the integration region.
|
|
226
|
+
label : str, optional
|
|
227
|
+
Label for the rectangle patch marking the integration window, used in the legend.
|
|
228
|
+
highlight_color : str, optional
|
|
229
|
+
Color of the rectangle edges highlighting the integration window. Default is 'red'.
|
|
230
|
+
**kwargs : dict, optional
|
|
231
|
+
Additional keyword arguments passed to `plot_slice` for customizing the plot (e.g., colormap, vmin, vmax).
|
|
232
|
+
|
|
233
|
+
Returns
|
|
234
|
+
-------
|
|
235
|
+
p1, p2, p3 : matplotlib.collections.QuadMesh
|
|
236
|
+
The plotted QuadMesh objects for the three cross-sections:
|
|
237
|
+
XY at fixed Z, XZ at fixed Y, and YZ at fixed X.
|
|
238
|
+
|
|
239
|
+
"""
|
|
240
|
+
data = self.data if data is None else data
|
|
241
|
+
center = self.center
|
|
242
|
+
window = self.window
|
|
243
|
+
|
|
244
|
+
# Create a figure and subplots
|
|
245
|
+
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
|
|
246
|
+
|
|
247
|
+
# Plot cross-section 1
|
|
248
|
+
slice_obj = [slice(None)] * data.ndim
|
|
249
|
+
slice_obj[2] = center[2]
|
|
250
|
+
|
|
251
|
+
p1 = plot_slice(data[slice_obj],
|
|
252
|
+
X=data[data.axes[0]],
|
|
253
|
+
Y=data[data.axes[1]],
|
|
254
|
+
ax=axes[0],
|
|
255
|
+
**kwargs)
|
|
256
|
+
ax = axes[0]
|
|
257
|
+
rect_diffuse = patches.Rectangle(
|
|
258
|
+
(center[0] - window[0],
|
|
259
|
+
center[1] - window[1]),
|
|
260
|
+
2 * window[0], 2 * window[1],
|
|
261
|
+
linewidth=1, edgecolor=highlight_color,
|
|
262
|
+
facecolor='none', transform=p1.get_transform(), label=label,
|
|
263
|
+
)
|
|
264
|
+
ax.add_patch(rect_diffuse)
|
|
265
|
+
|
|
266
|
+
if 'xlim' not in kwargs and width is not None:
|
|
267
|
+
ax.set(xlim=(center[0]-width/2,center[0]+width/2))
|
|
268
|
+
if 'ylim' not in kwargs and height is not None:
|
|
269
|
+
ax.set(ylim=(center[1]-height/2,center[1]+height/2))
|
|
270
|
+
|
|
271
|
+
# Plot cross-section 2
|
|
272
|
+
slice_obj = [slice(None)] * data.ndim
|
|
273
|
+
slice_obj[1] = center[1]
|
|
274
|
+
|
|
275
|
+
p2 = plot_slice(data[slice_obj],
|
|
276
|
+
X=data[data.axes[0]],
|
|
277
|
+
Y=data[data.axes[2]],
|
|
278
|
+
ax=axes[1],
|
|
279
|
+
**kwargs)
|
|
280
|
+
ax = axes[1]
|
|
281
|
+
rect_diffuse = patches.Rectangle(
|
|
282
|
+
(center[0] - window[0],
|
|
283
|
+
center[2] - window[2]),
|
|
284
|
+
2 * window[0], 2 * window[2],
|
|
285
|
+
linewidth=1, edgecolor=highlight_color,
|
|
286
|
+
facecolor='none', transform=p2.get_transform(), label=label,
|
|
287
|
+
)
|
|
288
|
+
ax.add_patch(rect_diffuse)
|
|
289
|
+
|
|
290
|
+
if 'xlim' not in kwargs and width is not None:
|
|
291
|
+
ax.set(xlim=(center[0]-width/2,center[0]+width/2))
|
|
292
|
+
if 'ylim' not in kwargs and height is not None:
|
|
293
|
+
ax.set(ylim=(center[2]-height/2,center[2]+height/2))
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
# Plot cross-section 3
|
|
297
|
+
slice_obj = [slice(None)] * data.ndim
|
|
298
|
+
slice_obj[0] = center[0]
|
|
299
|
+
|
|
300
|
+
p3 = plot_slice(data[slice_obj],
|
|
301
|
+
X=data[data.axes[1]],
|
|
302
|
+
Y=data[data.axes[2]],
|
|
303
|
+
ax=axes[2],
|
|
304
|
+
**kwargs)
|
|
305
|
+
ax = axes[2]
|
|
306
|
+
rect_diffuse = patches.Rectangle(
|
|
307
|
+
(center[1] - window[1],
|
|
308
|
+
center[2] - window[2]),
|
|
309
|
+
2 * window[1], 2 * window[2],
|
|
310
|
+
linewidth=1, edgecolor=highlight_color,
|
|
311
|
+
facecolor='none', transform=p3.get_transform(), label=label,
|
|
312
|
+
)
|
|
313
|
+
ax.add_patch(rect_diffuse)
|
|
314
|
+
|
|
315
|
+
if 'xlim' not in kwargs and width is not None:
|
|
316
|
+
ax.set(xlim=(center[1]-width/2,center[1]+width/2))
|
|
317
|
+
if 'ylim' not in kwargs and height is not None:
|
|
318
|
+
ax.set(ylim=(center[2]-height/2,center[2]+height/2))
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# Adjust subplot padding
|
|
322
|
+
fig.subplots_adjust(wspace=0.5)
|
|
323
|
+
|
|
324
|
+
if label is not None:
|
|
325
|
+
[ax.legend() for ax in axes]
|
|
326
|
+
|
|
327
|
+
plt.show()
|
|
328
|
+
|
|
329
|
+
return p1, p2, p3
|
|
330
|
+
|
|
331
|
+
def plot_integration_window(self, **kwargs):
|
|
332
|
+
"""
|
|
333
|
+
Plots the three principal cross-sections of the integration volume on a single figure.
|
|
334
|
+
|
|
335
|
+
Parameters
|
|
336
|
+
----------
|
|
337
|
+
**kwargs : keyword arguments, optional
|
|
338
|
+
Additional keyword arguments to customize the plot.
|
|
339
|
+
"""
|
|
340
|
+
data = self.integration_volume
|
|
341
|
+
center = self.center
|
|
342
|
+
|
|
343
|
+
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
|
|
344
|
+
|
|
345
|
+
# Plot cross section 1
|
|
346
|
+
slice_obj = [slice(None)] * data.ndim
|
|
347
|
+
slice_obj[2] = center[2]
|
|
348
|
+
p1 = plot_slice(data[slice_obj],
|
|
349
|
+
X=data[data.axes[0]],
|
|
350
|
+
Y=data[data.axes[1]],
|
|
351
|
+
ax=axes[0],
|
|
352
|
+
**kwargs)
|
|
353
|
+
axes[0].set_aspect(len(data[data.axes[0]].nxdata) / len(data[data.axes[1]].nxdata))
|
|
354
|
+
|
|
355
|
+
# Plot cross section 2
|
|
356
|
+
slice_obj = [slice(None)] * data.ndim
|
|
357
|
+
slice_obj[1] = center[1]
|
|
358
|
+
p3 = plot_slice(data[slice_obj],
|
|
359
|
+
X=data[data.axes[0]],
|
|
360
|
+
Y=data[data.axes[2]],
|
|
361
|
+
ax=axes[1],
|
|
362
|
+
**kwargs)
|
|
363
|
+
axes[1].set_aspect(len(data[data.axes[0]].nxdata) / len(data[data.axes[2]].nxdata))
|
|
364
|
+
|
|
365
|
+
# Plot cross section 3
|
|
366
|
+
slice_obj = [slice(None)] * data.ndim
|
|
367
|
+
slice_obj[0] = center[0]
|
|
368
|
+
p2 = plot_slice(data[slice_obj],
|
|
369
|
+
X=data[data.axes[1]],
|
|
370
|
+
Y=data[data.axes[2]],
|
|
371
|
+
ax=axes[2],
|
|
372
|
+
**kwargs)
|
|
373
|
+
axes[2].set_aspect(len(data[data.axes[1]].nxdata) / len(data[data.axes[2]].nxdata))
|
|
374
|
+
|
|
375
|
+
# Adjust subplot padding
|
|
376
|
+
fig.subplots_adjust(wspace=0.3)
|
|
377
|
+
|
|
378
|
+
plt.show()
|
|
379
|
+
|
|
380
|
+
return p1, p2, p3
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
data = load_data(r'C:\Users\steve\OneDrive\Documents\UCSB\Projects\RECd3P3\mini\15\3rot_hkli.nxs')
|
|
384
|
+
s = Scissors(data)
|
|
385
|
+
s.cut_data(center=(1,1,0), window=(0.5,0.2,0.2))
|
|
386
|
+
print(s.highlight_integration_window(vmin=0, vmax=100, width=10, height=10))
|
|
387
|
+
|
|
388
|
+
print(data.shape)
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from matplotlib.transforms import Affine2D
|
|
5
|
+
from matplotlib.markers import MarkerStyle
|
|
6
|
+
from matplotlib.ticker import MultipleLocator
|
|
7
|
+
from matplotlib import colors
|
|
8
|
+
from matplotlib import patches
|
|
9
|
+
from IPython.display import display, Markdown
|
|
10
|
+
from nexusformat.nexus import NXfield, NXdata, nxload, NeXusError, NXroot, NXentry, nxsave
|
|
11
|
+
from scipy import ndimage
|
|
12
|
+
from nxs_analysis_tools.datareduction import load_data, array_to_nxdata, plot_slice
|
|
13
|
+
|
|
14
|
+
# def plot_slice(data, X=None, Y=None, sum_axis=None, transpose=False, vmin=None, vmax=None,
|
|
15
|
+
# skew_angle=90, ax=None, xlim=None, ylim=None,
|
|
16
|
+
# xticks=None, yticks=None, cbar=True, logscale=False,
|
|
17
|
+
# symlogscale=False, cmap='viridis', linthresh=1,
|
|
18
|
+
# title=None, mdheading=None, cbartitle=None,
|
|
19
|
+
# **kwargs):
|
|
20
|
+
# """
|
|
21
|
+
# Plot a 2D slice of the provided dataset, with optional transformations
|
|
22
|
+
# and customizations.
|
|
23
|
+
#
|
|
24
|
+
# Parameters
|
|
25
|
+
# ----------
|
|
26
|
+
# data : :class:`nexusformat.nexus.NXdata` or ndarray
|
|
27
|
+
# The dataset to plot. Can be an `NXdata` object or a `numpy` array.
|
|
28
|
+
#
|
|
29
|
+
# X : NXfield, optional
|
|
30
|
+
# The X axis values. If None, a default range from 0 to the number of
|
|
31
|
+
# columns in `data` is used.
|
|
32
|
+
#
|
|
33
|
+
# Y : NXfield, optional
|
|
34
|
+
# The Y axis values. If None, a default range from 0 to the number of
|
|
35
|
+
# rows in `data` is used.
|
|
36
|
+
#
|
|
37
|
+
# sum_axis : int, optional
|
|
38
|
+
# If the input data is 3D, this specifies the axis to sum over in order
|
|
39
|
+
# to reduce the data to 2D for plotting. Required if `data` has three dimensions.
|
|
40
|
+
#
|
|
41
|
+
# transpose : bool, optional
|
|
42
|
+
# If True, transpose the dataset and its axes before plotting.
|
|
43
|
+
# Default is False.
|
|
44
|
+
#
|
|
45
|
+
# vmin : float, optional
|
|
46
|
+
# The minimum value for the color scale. If not provided, the minimum
|
|
47
|
+
# value of the dataset is used.
|
|
48
|
+
#
|
|
49
|
+
# vmax : float, optional
|
|
50
|
+
# The maximum value for the color scale. If not provided, the maximum
|
|
51
|
+
# value of the dataset is used.
|
|
52
|
+
#
|
|
53
|
+
# skew_angle : float, optional
|
|
54
|
+
# The angle in degrees to shear the plot. Default is 90 degrees (no skew).
|
|
55
|
+
#
|
|
56
|
+
# ax : matplotlib.axes.Axes, optional
|
|
57
|
+
# The `matplotlib` axis to plot on. If None, a new figure and axis will
|
|
58
|
+
# be created.
|
|
59
|
+
#
|
|
60
|
+
# xlim : tuple, optional
|
|
61
|
+
# The limits for the x-axis. If None, the limits are set automatically
|
|
62
|
+
# based on the data.
|
|
63
|
+
#
|
|
64
|
+
# ylim : tuple, optional
|
|
65
|
+
# The limits for the y-axis. If None, the limits are set automatically
|
|
66
|
+
# based on the data.
|
|
67
|
+
#
|
|
68
|
+
# xticks : float or list of float, optional
|
|
69
|
+
# The major tick interval or specific tick locations for the x-axis.
|
|
70
|
+
# Default is to use a minor tick interval of 1.
|
|
71
|
+
#
|
|
72
|
+
# yticks : float or list of float, optional
|
|
73
|
+
# The major tick interval or specific tick locations for the y-axis.
|
|
74
|
+
# Default is to use a minor tick interval of 1.
|
|
75
|
+
#
|
|
76
|
+
# cbar : bool, optional
|
|
77
|
+
# Whether to include a colorbar. Default is True.
|
|
78
|
+
#
|
|
79
|
+
# logscale : bool, optional
|
|
80
|
+
# Whether to use a logarithmic color scale. Default is False.
|
|
81
|
+
#
|
|
82
|
+
# symlogscale : bool, optional
|
|
83
|
+
# Whether to use a symmetrical logarithmic color scale. Default is False.
|
|
84
|
+
#
|
|
85
|
+
# cmap : str or Colormap, optional
|
|
86
|
+
# The colormap to use for the plot. Default is 'viridis'.
|
|
87
|
+
#
|
|
88
|
+
# linthresh : float, optional
|
|
89
|
+
# The linear threshold for symmetrical logarithmic scaling. Default is 1.
|
|
90
|
+
#
|
|
91
|
+
# title : str, optional
|
|
92
|
+
# The title for the plot. If None, no title is set.
|
|
93
|
+
#
|
|
94
|
+
# mdheading : str, optional
|
|
95
|
+
# A Markdown heading to display above the plot. If 'None' or not provided,
|
|
96
|
+
# no heading is displayed.
|
|
97
|
+
#
|
|
98
|
+
# cbartitle : str, optional
|
|
99
|
+
# The title for the colorbar. If None, the colorbar label will be set to
|
|
100
|
+
# the name of the signal.
|
|
101
|
+
#
|
|
102
|
+
# **kwargs
|
|
103
|
+
# Additional keyword arguments passed to `pcolormesh`.
|
|
104
|
+
#
|
|
105
|
+
# Returns
|
|
106
|
+
# -------
|
|
107
|
+
# p : :class:`matplotlib.collections.QuadMesh`
|
|
108
|
+
# The `matplotlib` QuadMesh object representing the plotted data.
|
|
109
|
+
# """
|
|
110
|
+
# is_array = False
|
|
111
|
+
# is_nxdata = False
|
|
112
|
+
#
|
|
113
|
+
# if isinstance(data, np.ndarray):
|
|
114
|
+
# is_array = True
|
|
115
|
+
# elif isinstance(data, (NXdata, NXfield)):
|
|
116
|
+
# is_nxdata = True
|
|
117
|
+
# else:
|
|
118
|
+
# raise TypeError(f"Unexpected data type: {type(data)}. "
|
|
119
|
+
# f"Supported types are np.ndarray and NXdata.")
|
|
120
|
+
#
|
|
121
|
+
# # If three-dimensional, demand sum_axis to reduce to two dimensions.
|
|
122
|
+
# if is_array and len(data.shape) == 3:
|
|
123
|
+
# assert sum_axis is not None, "sum_axis must be specified when data is a 3D array"
|
|
124
|
+
#
|
|
125
|
+
# data = data.sum(axis=sum_axis)
|
|
126
|
+
#
|
|
127
|
+
# if is_nxdata and len(data.shape) == 3:
|
|
128
|
+
# assert sum_axis is not None, "sum_axis must be specified when data is a 3D array"
|
|
129
|
+
#
|
|
130
|
+
# arr = data.nxsignal.nxdata
|
|
131
|
+
# arr = arr.sum(axis=sum_axis)
|
|
132
|
+
#
|
|
133
|
+
# # Create a 2D template from the original nxdata
|
|
134
|
+
# slice_obj = [slice(None)] * len(data.shape)
|
|
135
|
+
# slice_obj[sum_axis] = 0
|
|
136
|
+
#
|
|
137
|
+
# # Use the 2D template to create a new nxdata
|
|
138
|
+
# data = array_to_nxdata(arr, data[slice_obj])
|
|
139
|
+
#
|
|
140
|
+
# if is_array:
|
|
141
|
+
# if X is None:
|
|
142
|
+
# X = NXfield(np.linspace(0, data.shape[0], data.shape[0]), name='x')
|
|
143
|
+
# if Y is None:
|
|
144
|
+
# Y = NXfield(np.linspace(0, data.shape[1], data.shape[1]), name='y')
|
|
145
|
+
# if transpose:
|
|
146
|
+
# X, Y = Y, X
|
|
147
|
+
# data = data.transpose()
|
|
148
|
+
# data = NXdata(NXfield(data, name='value'), (X, Y))
|
|
149
|
+
# data_arr = data[data.signal].nxdata.transpose()
|
|
150
|
+
# elif is_nxdata:
|
|
151
|
+
# if X is None:
|
|
152
|
+
# X = data[data.axes[0]]
|
|
153
|
+
# if Y is None:
|
|
154
|
+
# Y = data[data.axes[1]]
|
|
155
|
+
# if transpose:
|
|
156
|
+
# X, Y = Y, X
|
|
157
|
+
# data = data.transpose()
|
|
158
|
+
# data_arr = data[data.signal].nxdata.transpose()
|
|
159
|
+
#
|
|
160
|
+
# # Display Markdown heading
|
|
161
|
+
# if mdheading is None:
|
|
162
|
+
# pass
|
|
163
|
+
# elif mdheading == "None":
|
|
164
|
+
# display(Markdown('### Figure'))
|
|
165
|
+
# else:
|
|
166
|
+
# display(Markdown('### Figure - ' + mdheading))
|
|
167
|
+
#
|
|
168
|
+
# # Inherit axes if user provides some
|
|
169
|
+
# if ax is not None:
|
|
170
|
+
# fig = ax.get_figure()
|
|
171
|
+
# # Otherwise set up some default axes
|
|
172
|
+
# else:
|
|
173
|
+
# fig = plt.figure()
|
|
174
|
+
# ax = fig.add_axes([0, 0, 1, 1])
|
|
175
|
+
#
|
|
176
|
+
# # If limits not provided, use extrema
|
|
177
|
+
# if vmin is None:
|
|
178
|
+
# vmin = data_arr.min()
|
|
179
|
+
# if vmax is None:
|
|
180
|
+
# vmax = data_arr.max()
|
|
181
|
+
#
|
|
182
|
+
# # Set norm (linear scale, logscale, or symlogscale)
|
|
183
|
+
# norm = colors.Normalize(vmin=vmin, vmax=vmax) # Default: linear scale
|
|
184
|
+
#
|
|
185
|
+
# if symlogscale:
|
|
186
|
+
# norm = colors.SymLogNorm(linthresh=linthresh, vmin=-1 * vmax, vmax=vmax)
|
|
187
|
+
# elif logscale:
|
|
188
|
+
# norm = colors.LogNorm(vmin=vmin, vmax=vmax)
|
|
189
|
+
#
|
|
190
|
+
# # Plot data
|
|
191
|
+
# p = ax.pcolormesh(X.nxdata, Y.nxdata, data_arr, shading='auto', norm=norm, cmap=cmap, **kwargs)
|
|
192
|
+
#
|
|
193
|
+
# ## Transform data to new coordinate system if necessary
|
|
194
|
+
# # Correct skew angle
|
|
195
|
+
# skew_angle_adj = 90 - skew_angle
|
|
196
|
+
# # Create blank 2D affine transformation
|
|
197
|
+
# t = Affine2D()
|
|
198
|
+
# # Scale y-axis to preserve norm while shearing
|
|
199
|
+
# t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180))
|
|
200
|
+
# # Shear along x-axis
|
|
201
|
+
# t += Affine2D().skew_deg(skew_angle_adj, 0)
|
|
202
|
+
# # Return to original y-axis scaling
|
|
203
|
+
# t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
204
|
+
# ## Correct for x-displacement after shearing
|
|
205
|
+
# # If ylims provided, use those
|
|
206
|
+
# if ylim is not None:
|
|
207
|
+
# # Set ylims
|
|
208
|
+
# ax.set(ylim=ylim)
|
|
209
|
+
# ymin, ymax = ylim
|
|
210
|
+
# # Else, use current ylims
|
|
211
|
+
# else:
|
|
212
|
+
# ymin, ymax = ax.get_ylim()
|
|
213
|
+
# # Use ylims to calculate translation (necessary to display axes in correct position)
|
|
214
|
+
# p.set_transform(t
|
|
215
|
+
# + Affine2D().translate(-ymin * np.sin(skew_angle_adj * np.pi / 180), 0)
|
|
216
|
+
# + ax.transData)
|
|
217
|
+
#
|
|
218
|
+
# # Set x limits
|
|
219
|
+
# if xlim is not None:
|
|
220
|
+
# xmin, xmax = xlim
|
|
221
|
+
# else:
|
|
222
|
+
# xmin, xmax = ax.get_xlim()
|
|
223
|
+
# if skew_angle <= 90:
|
|
224
|
+
# ax.set(xlim=(xmin, xmax + (ymax - ymin) / np.tan((90 - skew_angle_adj) * np.pi / 180)))
|
|
225
|
+
# else:
|
|
226
|
+
# ax.set(xlim=(xmin - (ymax - ymin) / np.tan((skew_angle_adj - 90) * np.pi / 180), xmax))
|
|
227
|
+
#
|
|
228
|
+
# # Correct aspect ratio for the x/y axes after transformation
|
|
229
|
+
# ax.set(aspect=np.cos(skew_angle_adj * np.pi / 180))
|
|
230
|
+
#
|
|
231
|
+
# # Add tick marks all around
|
|
232
|
+
# ax.tick_params(direction='in', top=True, right=True, which='both')
|
|
233
|
+
#
|
|
234
|
+
# # Set tick locations
|
|
235
|
+
# if xticks is None:
|
|
236
|
+
# # Add default minor ticks
|
|
237
|
+
# ax.xaxis.set_minor_locator(MultipleLocator(1))
|
|
238
|
+
# else:
|
|
239
|
+
# # Otherwise use user provided values
|
|
240
|
+
# ax.xaxis.set_major_locator(MultipleLocator(xticks))
|
|
241
|
+
# ax.xaxis.set_minor_locator(MultipleLocator(1))
|
|
242
|
+
# if yticks is None:
|
|
243
|
+
# # Add default minor ticks
|
|
244
|
+
# ax.yaxis.set_minor_locator(MultipleLocator(1))
|
|
245
|
+
# else:
|
|
246
|
+
# # Otherwise use user provided values
|
|
247
|
+
# ax.yaxis.set_major_locator(MultipleLocator(yticks))
|
|
248
|
+
# ax.yaxis.set_minor_locator(MultipleLocator(1))
|
|
249
|
+
#
|
|
250
|
+
# # Apply transform to tick marks
|
|
251
|
+
# for i in range(0, len(ax.xaxis.get_ticklines())):
|
|
252
|
+
# # Tick marker
|
|
253
|
+
# m = MarkerStyle(3)
|
|
254
|
+
# line = ax.xaxis.get_majorticklines()[i]
|
|
255
|
+
# if i % 2:
|
|
256
|
+
# # Top ticks (translation here makes their direction="in")
|
|
257
|
+
# m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
258
|
+
# # This first method shifts the top ticks horizontally to match the skew angle.
|
|
259
|
+
# # This does not look good in all cases.
|
|
260
|
+
# # line.set_transform(Affine2D().translate((ymax-ymin)*np.sin(skew_angle*np.pi/180),0) +
|
|
261
|
+
# # line.get_transform())
|
|
262
|
+
# # This second method skews the tick marks in place and
|
|
263
|
+
# # can sometimes lead to them being misaligned.
|
|
264
|
+
# line.set_transform(line.get_transform()) # This does nothing
|
|
265
|
+
# else:
|
|
266
|
+
# # Bottom ticks
|
|
267
|
+
# m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
268
|
+
#
|
|
269
|
+
# line.set_marker(m)
|
|
270
|
+
#
|
|
271
|
+
# for i in range(0, len(ax.xaxis.get_minorticklines())):
|
|
272
|
+
# m = MarkerStyle(2)
|
|
273
|
+
# line = ax.xaxis.get_minorticklines()[i]
|
|
274
|
+
# if i % 2:
|
|
275
|
+
# m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
276
|
+
# else:
|
|
277
|
+
# m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
278
|
+
#
|
|
279
|
+
# line.set_marker(m)
|
|
280
|
+
#
|
|
281
|
+
# if cbar:
|
|
282
|
+
# colorbar = fig.colorbar(p)
|
|
283
|
+
# if cbartitle is None:
|
|
284
|
+
# colorbar.set_label(data.signal)
|
|
285
|
+
#
|
|
286
|
+
# ax.set(
|
|
287
|
+
# xlabel=X.nxname,
|
|
288
|
+
# ylabel=Y.nxname,
|
|
289
|
+
# )
|
|
290
|
+
#
|
|
291
|
+
# if title is not None:
|
|
292
|
+
# ax.set_title(title)
|
|
293
|
+
#
|
|
294
|
+
# # Return the quadmesh object
|
|
295
|
+
# return p
|
|
296
|
+
|
|
297
|
+
data = load_data(r'C:\Users\steve\OneDrive\Documents\UCSB\Projects\RECd3P3\mini\15\3rot_hkli.nxs')
|
|
298
|
+
plot_slice(data[:,-0.2:0.2,:], vmin=0, vmax=100*10, sum_axis=1)
|
|
299
|
+
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.46 → nxs_analysis_tools-0.0.47}/src/nxs_analysis_tools/pairdistribution.py
RENAMED
|
File without changes
|
|
File without changes
|
{nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/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
|
|
File without changes
|
{nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_plot_slice_with_ndarray.py
RENAMED
|
File without changes
|
{nxs_analysis_tools-0.0.46 → nxs_analysis_tools-0.0.47}/tests/test_symmetrizer_rectangular_plane.py
RENAMED
|
File without changes
|