nxs-analysis-tools 0.0.23__py3-none-any.whl → 0.0.25__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.
Potentially problematic release.
This version of nxs-analysis-tools might be problematic. Click here for more details.
- _meta/__init__.py +1 -1
- nxs_analysis_tools/__init__.py +2 -2
- nxs_analysis_tools/datareduction.py +271 -18
- nxs_analysis_tools/pairdistribution.py +99 -179
- {nxs_analysis_tools-0.0.23.dist-info → nxs_analysis_tools-0.0.25.dist-info}/METADATA +21 -21
- nxs_analysis_tools-0.0.25.dist-info/RECORD +11 -0
- {nxs_analysis_tools-0.0.23.dist-info → nxs_analysis_tools-0.0.25.dist-info}/WHEEL +1 -1
- nxs_analysis_tools-0.0.23.dist-info/RECORD +0 -11
- {nxs_analysis_tools-0.0.23.dist-info → nxs_analysis_tools-0.0.25.dist-info}/LICENSE +0 -0
- {nxs_analysis_tools-0.0.23.dist-info → nxs_analysis_tools-0.0.25.dist-info}/top_level.txt +0 -0
_meta/__init__.py
CHANGED
nxs_analysis_tools/__init__.py
CHANGED
|
@@ -4,9 +4,9 @@ Reduce and transform nexus format (.nxs) scattering data.
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from _meta import __author__, __copyright__, __license__, __version__
|
|
7
|
-
from .datareduction import load_data, plot_slice, Scissors,
|
|
7
|
+
from .datareduction import load_data, plot_slice, reciprocal_lattice_params, Scissors, rotate_data
|
|
8
8
|
from .chess import TempDependence
|
|
9
9
|
|
|
10
10
|
# What to import when running "from nxs_analysis_tools import *"
|
|
11
11
|
__all__ = ['load_data', 'plot_slice', 'Scissors', 'TempDependence',
|
|
12
|
-
'reciprocal_lattice_params']
|
|
12
|
+
'reciprocal_lattice_params', 'rotate_data']
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Reduces scattering data into 2D and 1D datasets.
|
|
3
3
|
"""
|
|
4
|
-
|
|
4
|
+
import os
|
|
5
5
|
import numpy as np
|
|
6
6
|
import matplotlib.pyplot as plt
|
|
7
7
|
from matplotlib.transforms import Affine2D
|
|
@@ -10,9 +10,11 @@ from matplotlib.ticker import MultipleLocator
|
|
|
10
10
|
from matplotlib import colors
|
|
11
11
|
from matplotlib import patches
|
|
12
12
|
from IPython.display import display, Markdown
|
|
13
|
-
from nexusformat.nexus import NXfield, NXdata, nxload, NeXusError
|
|
13
|
+
from nexusformat.nexus import NXfield, NXdata, nxload, NeXusError, NXroot, NXentry, nxsave
|
|
14
|
+
from scipy import ndimage
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
# Specify items on which users are allowed to perform standalone imports
|
|
17
|
+
__all__ = ['load_data', 'plot_slice', 'Scissors', 'reciprocal_lattice_params', 'rotate_data', 'array_to_nxdata', 'Padder']
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
def load_data(path):
|
|
@@ -39,6 +41,31 @@ def load_data(path):
|
|
|
39
41
|
return g.entry.data
|
|
40
42
|
|
|
41
43
|
|
|
44
|
+
def array_to_nxdata(array, data_template, signal_name='counts'):
|
|
45
|
+
"""
|
|
46
|
+
Create an NXdata object from an input array and an NXdata template, with an optional signal name.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
array : array-like
|
|
51
|
+
The data array to be included in the NXdata object.
|
|
52
|
+
|
|
53
|
+
data_template : NXdata
|
|
54
|
+
An NXdata object serving as a template, which provides information about axes and other metadata.
|
|
55
|
+
|
|
56
|
+
signal_name : str, optional
|
|
57
|
+
The name of the signal within the NXdata object. If not provided,
|
|
58
|
+
the default signal name 'counts' is used.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
NXdata
|
|
63
|
+
An NXdata object containing the input data array and associated axes based on the template.
|
|
64
|
+
"""
|
|
65
|
+
d = data_template
|
|
66
|
+
return NXdata(NXfield(array, name=signal_name), tuple([d[d.axes[i]] for i in range(len(d.axes))]))
|
|
67
|
+
|
|
68
|
+
|
|
42
69
|
def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew_angle=90,
|
|
43
70
|
ax=None, xlim=None, ylim=None, xticks=None, yticks=None, cbar=True, logscale=False,
|
|
44
71
|
symlogscale=False, cmap='viridis', linthresh=1, title=None, mdheading=None, cbartitle=None,
|
|
@@ -113,7 +140,6 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
113
140
|
|
|
114
141
|
"""
|
|
115
142
|
if type(data) == np.ndarray:
|
|
116
|
-
data = data.transpose()
|
|
117
143
|
if X is None:
|
|
118
144
|
X = NXfield(np.linspace(0, data.shape[1], data.shape[1]), name='x')
|
|
119
145
|
if Y is None:
|
|
@@ -121,7 +147,8 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
121
147
|
if transpose:
|
|
122
148
|
X, Y = Y, X
|
|
123
149
|
data = data.transpose()
|
|
124
|
-
data = NXdata(NXfield(data, name='value'), (X,Y))
|
|
150
|
+
data = NXdata(NXfield(data, name='value'), (X, Y))
|
|
151
|
+
data_arr = data
|
|
125
152
|
elif type(data) == NXdata or type(data) == NXfield:
|
|
126
153
|
if X is None:
|
|
127
154
|
X = data[data.axes[0]]
|
|
@@ -130,11 +157,10 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
130
157
|
if transpose:
|
|
131
158
|
X, Y = Y, X
|
|
132
159
|
data = data.transpose()
|
|
160
|
+
data_arr = data[data.signal].nxdata.transpose()
|
|
133
161
|
else:
|
|
134
162
|
raise TypeError(f"Unexpected data type: {type(data)}. Supported types are np.ndarray and NXdata.")
|
|
135
163
|
|
|
136
|
-
data_arr = data[data.signal].nxdata.transpose()
|
|
137
|
-
|
|
138
164
|
# Display Markdown heading
|
|
139
165
|
if mdheading is None:
|
|
140
166
|
pass
|
|
@@ -171,15 +197,15 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
171
197
|
|
|
172
198
|
## Transform data to new coordinate system if necessary
|
|
173
199
|
# Correct skew angle
|
|
174
|
-
|
|
200
|
+
skew_angle_adj = 90 - skew_angle
|
|
175
201
|
# Create blank 2D affine transformation
|
|
176
202
|
t = Affine2D()
|
|
177
203
|
# Scale y-axis to preserve norm while shearing
|
|
178
|
-
t += Affine2D().scale(1, np.cos(
|
|
204
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180))
|
|
179
205
|
# Shear along x-axis
|
|
180
|
-
t += Affine2D().skew_deg(
|
|
206
|
+
t += Affine2D().skew_deg(skew_angle_adj, 0)
|
|
181
207
|
# Return to original y-axis scaling
|
|
182
|
-
t += Affine2D().scale(1, np.cos(
|
|
208
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
183
209
|
## Correct for x-displacement after shearing
|
|
184
210
|
# If ylims provided, use those
|
|
185
211
|
if ylim is not None:
|
|
@@ -190,17 +216,20 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
190
216
|
else:
|
|
191
217
|
ymin, ymax = ax.get_ylim()
|
|
192
218
|
# Use ylims to calculate translation (necessary to display axes in correct position)
|
|
193
|
-
p.set_transform(t + Affine2D().translate(-ymin * np.sin(
|
|
219
|
+
p.set_transform(t + Affine2D().translate(-ymin * np.sin(skew_angle_adj * np.pi / 180), 0) + ax.transData)
|
|
194
220
|
|
|
195
221
|
# Set x limits
|
|
196
222
|
if xlim is not None:
|
|
197
223
|
xmin, xmax = xlim
|
|
198
224
|
else:
|
|
199
225
|
xmin, xmax = ax.get_xlim()
|
|
200
|
-
|
|
226
|
+
if skew_angle <= 90:
|
|
227
|
+
ax.set(xlim=(xmin, xmax + (ymax - ymin) / np.tan((90 - skew_angle_adj) * np.pi / 180)))
|
|
228
|
+
else:
|
|
229
|
+
ax.set(xlim=(xmin - (ymax - ymin) / np.tan((skew_angle_adj - 90) * np.pi / 180), xmax))
|
|
201
230
|
|
|
202
231
|
# Correct aspect ratio for the x/y axes after transformation
|
|
203
|
-
ax.set(aspect=np.cos(
|
|
232
|
+
ax.set(aspect=np.cos(skew_angle_adj * np.pi / 180))
|
|
204
233
|
|
|
205
234
|
# Add tick marks all around
|
|
206
235
|
ax.tick_params(direction='in', top=True, right=True, which='both')
|
|
@@ -228,7 +257,7 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
228
257
|
line = ax.xaxis.get_majorticklines()[i]
|
|
229
258
|
if i % 2:
|
|
230
259
|
# Top ticks (translation here makes their direction="in")
|
|
231
|
-
m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(
|
|
260
|
+
m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
232
261
|
# This first method shifts the top ticks horizontally to match the skew angle.
|
|
233
262
|
# This does not look good in all cases.
|
|
234
263
|
# line.set_transform(Affine2D().translate((ymax-ymin)*np.sin(skew_angle*np.pi/180),0) +
|
|
@@ -238,7 +267,7 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
238
267
|
line.set_transform(line.get_transform()) # This does nothing
|
|
239
268
|
else:
|
|
240
269
|
# Bottom ticks
|
|
241
|
-
m._transform.set(Affine2D().skew_deg(
|
|
270
|
+
m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
242
271
|
|
|
243
272
|
line.set_marker(m)
|
|
244
273
|
|
|
@@ -246,9 +275,9 @@ def plot_slice(data, X=None, Y=None, transpose=False, vmin=None, vmax=None, skew
|
|
|
246
275
|
m = MarkerStyle(2)
|
|
247
276
|
line = ax.xaxis.get_minorticklines()[i]
|
|
248
277
|
if i % 2:
|
|
249
|
-
m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(
|
|
278
|
+
m._transform.set(Affine2D().translate(0, -1) + Affine2D().skew_deg(skew_angle_adj, 0))
|
|
250
279
|
else:
|
|
251
|
-
m._transform.set(Affine2D().skew_deg(
|
|
280
|
+
m._transform.set(Affine2D().skew_deg(skew_angle_adj, 0))
|
|
252
281
|
|
|
253
282
|
line.set_marker(m)
|
|
254
283
|
|
|
@@ -624,3 +653,227 @@ def reciprocal_lattice_params(lattice_params):
|
|
|
624
653
|
gamma_star = np.rad2deg(np.arccos((np.cos(alpha) * np.cos(beta) - np.cos(gamma)) / (np.sin(alpha) * np.sin(beta))))
|
|
625
654
|
|
|
626
655
|
return a_star, b_star, c_star, alpha_star, beta_star, gamma_star
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
def rotate_data(data, lattice_angle, rotation_angle, rotation_axis):
|
|
659
|
+
"""
|
|
660
|
+
Rotates 3D data around a specified axis.
|
|
661
|
+
|
|
662
|
+
Parameters
|
|
663
|
+
----------
|
|
664
|
+
data : :class:`nexusformat.nexus.NXdata`
|
|
665
|
+
Input data.
|
|
666
|
+
lattice_angle : float
|
|
667
|
+
Angle between the two in-plane lattice axes in degrees.
|
|
668
|
+
rotation_angle : float
|
|
669
|
+
Angle of rotation in degrees.
|
|
670
|
+
rotation_axis : int
|
|
671
|
+
Axis of rotation (0, 1, or 2).
|
|
672
|
+
|
|
673
|
+
Returns
|
|
674
|
+
-------
|
|
675
|
+
rotated_data : :class:`nexusformat.nexus.NXdata`
|
|
676
|
+
Rotated data as an NXdata object.
|
|
677
|
+
"""
|
|
678
|
+
# Define output array
|
|
679
|
+
output_array = np.zeros(data[data.signal].shape)
|
|
680
|
+
|
|
681
|
+
# Define transformation
|
|
682
|
+
skew_angle_adj = 90 - lattice_angle
|
|
683
|
+
t = Affine2D()
|
|
684
|
+
# Scale y-axis to preserve norm while shearing
|
|
685
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180))
|
|
686
|
+
# Shear along x-axis
|
|
687
|
+
t += Affine2D().skew_deg(skew_angle_adj, 0)
|
|
688
|
+
# Return to original y-axis scaling
|
|
689
|
+
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
690
|
+
|
|
691
|
+
for i in range(len(data[data.axes[rotation_axis]])):
|
|
692
|
+
# Identify current slice
|
|
693
|
+
if rotation_axis == 0:
|
|
694
|
+
sliced_data = data[i, :, :]
|
|
695
|
+
elif rotation_axis == 1:
|
|
696
|
+
sliced_data = data[:, i, :]
|
|
697
|
+
elif rotation_axis == 2:
|
|
698
|
+
sliced_data = data[:, :, i]
|
|
699
|
+
else:
|
|
700
|
+
sliced_data = None
|
|
701
|
+
|
|
702
|
+
p = Padder(sliced_data)
|
|
703
|
+
padding = tuple([len(sliced_data[axis]) for axis in sliced_data.axes])
|
|
704
|
+
counts = p.pad(padding)
|
|
705
|
+
|
|
706
|
+
counts_skewed = ndimage.affine_transform(counts,
|
|
707
|
+
t.inverted().get_matrix()[:2, :2],
|
|
708
|
+
offset=[counts.shape[0] / 2 * np.sin(skew_angle_adj * np.pi / 180), 0],
|
|
709
|
+
order=0,
|
|
710
|
+
)
|
|
711
|
+
scale1 = np.cos(skew_angle_adj * np.pi / 180)
|
|
712
|
+
counts_scaled1 = ndimage.affine_transform(counts_skewed,
|
|
713
|
+
Affine2D().scale(scale1, 1).get_matrix()[:2, :2],
|
|
714
|
+
offset=[(1 - scale1) * counts.shape[0] / 2, 0],
|
|
715
|
+
order=0,
|
|
716
|
+
)
|
|
717
|
+
scale2 = counts.shape[0] / counts.shape[1]
|
|
718
|
+
counts_scaled2 = ndimage.affine_transform(counts_scaled1,
|
|
719
|
+
Affine2D().scale(scale2, 1).get_matrix()[:2, :2],
|
|
720
|
+
offset=[(1 - scale2) * counts.shape[0] / 2, 0],
|
|
721
|
+
order=0,
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
counts_rotated = ndimage.rotate(counts_scaled2, rotation_angle, reshape=False, order=0)
|
|
725
|
+
|
|
726
|
+
counts_unscaled2 = ndimage.affine_transform(counts_rotated,
|
|
727
|
+
Affine2D().scale(scale2, 1).inverted().get_matrix()[:2, :2],
|
|
728
|
+
offset=[-(1 - scale2) * counts.shape[
|
|
729
|
+
0] / 2 / scale2, 0],
|
|
730
|
+
order=0,
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
counts_unscaled1 = ndimage.affine_transform(counts_unscaled2,
|
|
734
|
+
Affine2D().scale(scale1,
|
|
735
|
+
1).inverted().get_matrix()[:2, :2],
|
|
736
|
+
offset=[-(1 - scale1) * counts.shape[
|
|
737
|
+
0] / 2 / scale1, 0],
|
|
738
|
+
order=0,
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
counts_unskewed = ndimage.affine_transform(counts_unscaled1,
|
|
742
|
+
t.get_matrix()[:2, :2],
|
|
743
|
+
offset=[
|
|
744
|
+
(-counts.shape[0] / 2 * np.sin(skew_angle_adj * np.pi / 180)),
|
|
745
|
+
0],
|
|
746
|
+
order=0,
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
counts_unpadded = p.unpad(counts_unskewed)
|
|
750
|
+
|
|
751
|
+
# Write current slice
|
|
752
|
+
if rotation_axis == 0:
|
|
753
|
+
output_array[i, :, :] = counts_unpadded
|
|
754
|
+
elif rotation_axis == 1:
|
|
755
|
+
output_array[:, i, :] = counts_unpadded
|
|
756
|
+
elif rotation_axis == 2:
|
|
757
|
+
output_array[:, :, i] = counts_unpadded
|
|
758
|
+
|
|
759
|
+
return NXdata(NXfield(output_array, name='counts'),
|
|
760
|
+
(data[data.axes[0]], data[data.axes[1]], data[data.axes[2]]))
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
class Padder():
|
|
764
|
+
"""
|
|
765
|
+
A class to pad and unpad datasets with a symmetric region of zeros.
|
|
766
|
+
"""
|
|
767
|
+
|
|
768
|
+
def __init__(self, data=None):
|
|
769
|
+
"""
|
|
770
|
+
Initialize the Symmetrizer3D object.
|
|
771
|
+
|
|
772
|
+
Parameters
|
|
773
|
+
----------
|
|
774
|
+
data : NXdata, optional
|
|
775
|
+
The input data to be symmetrized. If provided, the `set_data` method is called to set the data.
|
|
776
|
+
|
|
777
|
+
"""
|
|
778
|
+
self.padded = None
|
|
779
|
+
self.padding = None
|
|
780
|
+
if data is not None:
|
|
781
|
+
self.set_data(data)
|
|
782
|
+
|
|
783
|
+
def set_data(self, data):
|
|
784
|
+
"""
|
|
785
|
+
Set the input data for symmetrization.
|
|
786
|
+
|
|
787
|
+
Parameters
|
|
788
|
+
----------
|
|
789
|
+
data : NXdata
|
|
790
|
+
The input data to be symmetrized.
|
|
791
|
+
|
|
792
|
+
"""
|
|
793
|
+
self.data = data
|
|
794
|
+
|
|
795
|
+
self.steps = tuple([(data[axis].nxdata[1] - data[axis].nxdata[0]) for axis in data.axes])
|
|
796
|
+
|
|
797
|
+
# Absolute value of the maximum value; assumes the domain of the input is symmetric (eg, -H_min = H_max)
|
|
798
|
+
self.maxes = tuple([data[axis].nxdata.max() for axis in data.axes])
|
|
799
|
+
|
|
800
|
+
def pad(self, padding):
|
|
801
|
+
"""
|
|
802
|
+
Symmetrically pads the data with zero values.
|
|
803
|
+
|
|
804
|
+
Parameters
|
|
805
|
+
----------
|
|
806
|
+
padding : tuple
|
|
807
|
+
The number of zero-value pixels to add along each edge of the array.
|
|
808
|
+
"""
|
|
809
|
+
data = self.data
|
|
810
|
+
self.padding = padding
|
|
811
|
+
|
|
812
|
+
padded_shape = tuple([data[data.signal].nxdata.shape[i] + self.padding[i] * 2 for i in range(data.ndim)])
|
|
813
|
+
|
|
814
|
+
# Create padded dataset
|
|
815
|
+
padded = np.zeros(padded_shape)
|
|
816
|
+
|
|
817
|
+
slice_obj = [slice(None)] * data.ndim
|
|
818
|
+
for i, _ in enumerate(slice_obj):
|
|
819
|
+
slice_obj[i] = slice(self.padding[i], -self.padding[i], None)
|
|
820
|
+
slice_obj = tuple(slice_obj)
|
|
821
|
+
padded[slice_obj] = data[data.signal].nxdata
|
|
822
|
+
|
|
823
|
+
padmaxes = tuple([self.maxes[i] + self.padding[i] * self.steps[i] for i in range(data.ndim)])
|
|
824
|
+
|
|
825
|
+
padded = NXdata(NXfield(padded, name=data.signal),
|
|
826
|
+
tuple([NXfield(np.linspace(-padmaxes[i], padmaxes[i], padded_shape[i]),
|
|
827
|
+
name=data.axes[i])
|
|
828
|
+
for i in range(data.ndim)]))
|
|
829
|
+
|
|
830
|
+
self.padded = padded
|
|
831
|
+
return padded
|
|
832
|
+
|
|
833
|
+
def save(self, fout_name=None):
|
|
834
|
+
"""
|
|
835
|
+
Saves the padded dataset to a .nxs file.
|
|
836
|
+
|
|
837
|
+
Parameters
|
|
838
|
+
----------
|
|
839
|
+
fout_name : str, optional
|
|
840
|
+
The output file name. Default is padded_(Hpadding)_(Kpadding)_(Lpadding).nxs
|
|
841
|
+
"""
|
|
842
|
+
padH, padK, padL = self.padding
|
|
843
|
+
|
|
844
|
+
# Save padded dataset
|
|
845
|
+
print("Saving padded dataset...")
|
|
846
|
+
f = NXroot()
|
|
847
|
+
f['entry'] = NXentry()
|
|
848
|
+
f['entry']['data'] = self.padded
|
|
849
|
+
if fout_name is None:
|
|
850
|
+
fout_name = 'padded_' + str(padH) + '_' + str(padK) + '_' + str(padL) + '.nxs'
|
|
851
|
+
nxsave(fout_name, f)
|
|
852
|
+
print("Output file saved to: " + os.path.join(os.getcwd(), fout_name))
|
|
853
|
+
|
|
854
|
+
def unpad(self, data):
|
|
855
|
+
"""
|
|
856
|
+
Removes the padded region from the data.
|
|
857
|
+
|
|
858
|
+
Parameters
|
|
859
|
+
----------
|
|
860
|
+
data : ndarray or NXdata
|
|
861
|
+
The padded data from which to remove the padding.
|
|
862
|
+
|
|
863
|
+
Returns
|
|
864
|
+
-------
|
|
865
|
+
ndarray or NXdata
|
|
866
|
+
The unpadded data, with the symmetric padding region removed.
|
|
867
|
+
|
|
868
|
+
Notes
|
|
869
|
+
-----
|
|
870
|
+
This method removes the symmetric padding region that was added using the `pad` method. It returns the data
|
|
871
|
+
without the padded region.
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
"""
|
|
875
|
+
slice_obj = [slice(None)] * data.ndim
|
|
876
|
+
for i in range(data.ndim):
|
|
877
|
+
slice_obj[i] = slice(self.padding[i], -self.padding[i], None)
|
|
878
|
+
slice_obj = tuple(slice_obj)
|
|
879
|
+
return data[slice_obj]
|
|
@@ -8,128 +8,7 @@ import matplotlib.pyplot as plt
|
|
|
8
8
|
from matplotlib.transforms import Affine2D
|
|
9
9
|
from nexusformat.nexus import nxsave, NXroot, NXentry, NXdata, NXfield
|
|
10
10
|
import numpy as np
|
|
11
|
-
from
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Padder():
|
|
16
|
-
"""
|
|
17
|
-
A class to pad and unpad datasets with a symmetric region of zeros.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(self, data=None):
|
|
21
|
-
"""
|
|
22
|
-
Initialize the Symmetrizer3D object.
|
|
23
|
-
|
|
24
|
-
Parameters
|
|
25
|
-
----------
|
|
26
|
-
data : NXdata, optional
|
|
27
|
-
The input data to be symmetrized. If provided, the `set_data` method is called to set the data.
|
|
28
|
-
|
|
29
|
-
"""
|
|
30
|
-
self.padded = None
|
|
31
|
-
self.padding = None
|
|
32
|
-
if data is not None:
|
|
33
|
-
self.set_data(data)
|
|
34
|
-
|
|
35
|
-
def set_data(self, data):
|
|
36
|
-
"""
|
|
37
|
-
Set the input data for symmetrization.
|
|
38
|
-
|
|
39
|
-
Parameters
|
|
40
|
-
----------
|
|
41
|
-
data : NXdata
|
|
42
|
-
The input data to be symmetrized.
|
|
43
|
-
|
|
44
|
-
"""
|
|
45
|
-
self.data = data
|
|
46
|
-
|
|
47
|
-
self.steps = tuple([(data[axis].nxdata[1] - data[axis].nxdata[0]) for axis in data.axes])
|
|
48
|
-
|
|
49
|
-
# Absolute value of the maximum value; assumes the domain of the input is symmetric (eg, -H_min = H_max)
|
|
50
|
-
self.maxes = tuple([data[axis].nxdata.max() for axis in data.axes])
|
|
51
|
-
|
|
52
|
-
def pad(self, padding):
|
|
53
|
-
"""
|
|
54
|
-
Symmetrically pads the data with zero values.
|
|
55
|
-
|
|
56
|
-
Parameters
|
|
57
|
-
----------
|
|
58
|
-
padding : tuple
|
|
59
|
-
The number of zero-value pixels to add along each edge of the array.
|
|
60
|
-
"""
|
|
61
|
-
data = self.data
|
|
62
|
-
self.padding = padding
|
|
63
|
-
|
|
64
|
-
padded_shape = tuple([data[data.signal].nxdata.shape[i] + self.padding[i] * 2 for i in range(data.ndim)])
|
|
65
|
-
|
|
66
|
-
# Create padded dataset
|
|
67
|
-
padded = np.zeros(padded_shape)
|
|
68
|
-
|
|
69
|
-
slice_obj = [slice(None)] * data.ndim
|
|
70
|
-
for i, _ in enumerate(slice_obj):
|
|
71
|
-
slice_obj[i] = slice(self.padding[i], -self.padding[i], None)
|
|
72
|
-
slice_obj = tuple(slice_obj)
|
|
73
|
-
padded[slice_obj] = data[data.signal].nxdata
|
|
74
|
-
|
|
75
|
-
padmaxes = tuple([self.maxes[i] + self.padding[i] * self.steps[i] for i in range(data.ndim)])
|
|
76
|
-
|
|
77
|
-
padded = NXdata(NXfield(padded, name=data.signal),
|
|
78
|
-
tuple([NXfield(np.linspace(-padmaxes[i], padmaxes[i], padded_shape[i]),
|
|
79
|
-
name=data.axes[i])
|
|
80
|
-
for i in range(data.ndim)]))
|
|
81
|
-
|
|
82
|
-
self.padded = padded
|
|
83
|
-
return padded
|
|
84
|
-
|
|
85
|
-
def save(self, fout_name=None):
|
|
86
|
-
"""
|
|
87
|
-
Saves the padded dataset to a .nxs file.
|
|
88
|
-
|
|
89
|
-
Parameters
|
|
90
|
-
----------
|
|
91
|
-
fout_name : str, optional
|
|
92
|
-
The output file name. Default is padded_(Hpadding)_(Kpadding)_(Lpadding).nxs
|
|
93
|
-
"""
|
|
94
|
-
padH, padK, padL = self.padding
|
|
95
|
-
|
|
96
|
-
# Save padded dataset
|
|
97
|
-
print("Saving padded dataset...")
|
|
98
|
-
f = NXroot()
|
|
99
|
-
f['entry'] = NXentry()
|
|
100
|
-
f['entry']['data'] = self.padded
|
|
101
|
-
if fout_name is None:
|
|
102
|
-
fout_name = 'padded_' + str(padH) + '_' + str(padK) + '_' + str(padL) + '.nxs'
|
|
103
|
-
nxsave(fout_name, f)
|
|
104
|
-
print("Output file saved to: " + os.path.join(os.getcwd(), fout_name))
|
|
105
|
-
|
|
106
|
-
def unpad(self, data):
|
|
107
|
-
"""
|
|
108
|
-
Removes the padded region from the data.
|
|
109
|
-
|
|
110
|
-
Parameters
|
|
111
|
-
----------
|
|
112
|
-
data : ndarray or NXdata
|
|
113
|
-
The padded data from which to remove the padding.
|
|
114
|
-
|
|
115
|
-
Returns
|
|
116
|
-
-------
|
|
117
|
-
ndarray or NXdata
|
|
118
|
-
The unpadded data, with the symmetric padding region removed.
|
|
119
|
-
|
|
120
|
-
Notes
|
|
121
|
-
-----
|
|
122
|
-
This method removes the symmetric padding region that was added using the `pad` method. It returns the data
|
|
123
|
-
without the padded region.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
"""
|
|
127
|
-
slice_obj = [slice(None)] * data.ndim
|
|
128
|
-
for i in range(data.ndim):
|
|
129
|
-
slice_obj[i] = slice(self.padding[i], -self.padding[i], None)
|
|
130
|
-
slice_obj = tuple(slice_obj)
|
|
131
|
-
return data[slice_obj]
|
|
132
|
-
|
|
11
|
+
from .datareduction import plot_slice, reciprocal_lattice_params, Padder
|
|
133
12
|
|
|
134
13
|
class Symmetrizer2D:
|
|
135
14
|
"""
|
|
@@ -185,7 +64,7 @@ class Symmetrizer2D:
|
|
|
185
64
|
t += Affine2D().scale(1, np.cos(skew_angle_adj * np.pi / 180)).inverted()
|
|
186
65
|
self.transform = t
|
|
187
66
|
|
|
188
|
-
# Calculate number of rotations needed to
|
|
67
|
+
# Calculate number of rotations needed to reconstruct the dataset
|
|
189
68
|
if mirror:
|
|
190
69
|
rotations = abs(int(360 / (theta_max - theta_min) / 2))
|
|
191
70
|
else:
|
|
@@ -368,24 +247,53 @@ class Symmetrizer3D:
|
|
|
368
247
|
A class to symmetrize 3D datasets.
|
|
369
248
|
"""
|
|
370
249
|
|
|
371
|
-
def __init__(self, data):
|
|
250
|
+
def __init__(self, data=None):
|
|
372
251
|
"""
|
|
373
252
|
Initialize the Symmetrizer3D object.
|
|
374
253
|
|
|
375
254
|
Parameters
|
|
376
255
|
----------
|
|
377
|
-
data : NXdata
|
|
256
|
+
data : NXdata, optional
|
|
378
257
|
The input 3D dataset to be symmetrized.
|
|
379
258
|
|
|
380
259
|
"""
|
|
260
|
+
|
|
261
|
+
self.a, self.b, self.c, self.al, self.be, self.ga = [None] * 6
|
|
262
|
+
self.a_star, self.b_star, self.c_star, self.al_star, self.be_star, self.ga_star = [None] * 6
|
|
263
|
+
self.lattice_params = None
|
|
264
|
+
self.reciprocal_lattice_params = None
|
|
381
265
|
self.symmetrized = None
|
|
382
266
|
self.data = data
|
|
383
|
-
self.q1 = data[data.axes[0]]
|
|
384
|
-
self.q2 = data[data.axes[1]]
|
|
385
|
-
self.q3 = data[data.axes[2]]
|
|
386
267
|
self.plane1symmetrizer = Symmetrizer2D()
|
|
387
268
|
self.plane2symmetrizer = Symmetrizer2D()
|
|
388
269
|
self.plane3symmetrizer = Symmetrizer2D()
|
|
270
|
+
|
|
271
|
+
if data is not None:
|
|
272
|
+
self.q1 = data[data.axes[0]]
|
|
273
|
+
self.q2 = data[data.axes[1]]
|
|
274
|
+
self.q3 = data[data.axes[2]]
|
|
275
|
+
self.plane1 = self.q1.nxname + self.q2.nxname
|
|
276
|
+
self.plane2 = self.q1.nxname + self.q3.nxname
|
|
277
|
+
self.plane3 = self.q2.nxname + self.q3.nxname
|
|
278
|
+
|
|
279
|
+
print("Plane 1: " + self.plane1)
|
|
280
|
+
print("Plane 2: " + self.plane2)
|
|
281
|
+
print("Plane 3: " + self.plane3)
|
|
282
|
+
|
|
283
|
+
def set_data(self, data):
|
|
284
|
+
"""
|
|
285
|
+
Sets the data to be symmetrized.
|
|
286
|
+
|
|
287
|
+
Parameters
|
|
288
|
+
----------
|
|
289
|
+
data : NXdata
|
|
290
|
+
The input 3D dataset to be symmetrized.
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
self.data = data
|
|
294
|
+
self.q1 = data[data.axes[0]]
|
|
295
|
+
self.q2 = data[data.axes[1]]
|
|
296
|
+
self.q3 = data[data.axes[2]]
|
|
389
297
|
self.plane1 = self.q1.nxname + self.q2.nxname
|
|
390
298
|
self.plane2 = self.q1.nxname + self.q3.nxname
|
|
391
299
|
self.plane3 = self.q2.nxname + self.q3.nxname
|
|
@@ -394,6 +302,12 @@ class Symmetrizer3D:
|
|
|
394
302
|
print("Plane 2: " + self.plane2)
|
|
395
303
|
print("Plane 3: " + self.plane3)
|
|
396
304
|
|
|
305
|
+
def set_lattice_params(self, lattice_params):
|
|
306
|
+
self.a, self.b, self.c, self.al, self.be, self.ga = lattice_params
|
|
307
|
+
self.lattice_params = lattice_params
|
|
308
|
+
self.reciprocal_lattice_params = reciprocal_lattice_params(lattice_params)
|
|
309
|
+
self.a_star, self.b_star, self.c_star, self.al_star, self.be_star, self.ga_star = self.reciprocal_lattice_params
|
|
310
|
+
|
|
397
311
|
def symmetrize(self):
|
|
398
312
|
"""
|
|
399
313
|
Perform the symmetrization of the 3D dataset.
|
|
@@ -491,7 +405,7 @@ def generate_gaussian(H, K, L, amp, stddev, lattice_params, coeffs=None):
|
|
|
491
405
|
coeffs = [1, 0, 1, 0, 1, 0]
|
|
492
406
|
a, b, c, al, be, ga = lattice_params
|
|
493
407
|
a_, b_, c_, al_, be_, ga_ = reciprocal_lattice_params((a, b, c, al, be, ga))
|
|
494
|
-
H, K, L = np.meshgrid(H, K, L)
|
|
408
|
+
H, K, L = np.meshgrid(H, K, L, indexing='ij')
|
|
495
409
|
gaussian = amp * np.exp(-(coeffs[0] * H ** 2 +
|
|
496
410
|
coeffs[1] * (b_ * a_ / (a_ ** 2)) * H * K +
|
|
497
411
|
coeffs[2] * (b_ / a_) ** 2 * K ** 2 +
|
|
@@ -502,16 +416,25 @@ def generate_gaussian(H, K, L, amp, stddev, lattice_params, coeffs=None):
|
|
|
502
416
|
gaussian = gaussian.transpose(1, 0, 2)
|
|
503
417
|
elif gaussian.ndim == 2:
|
|
504
418
|
gaussian = gaussian.transpose()
|
|
505
|
-
return gaussian.transpose(1,0,2)
|
|
419
|
+
return gaussian.transpose(1, 0, 2)
|
|
506
420
|
|
|
507
421
|
|
|
508
422
|
class Puncher:
|
|
509
423
|
def __init__(self):
|
|
424
|
+
self.punched = None
|
|
425
|
+
self.data = None
|
|
426
|
+
self.H, self.K, self.L = [None] * 3
|
|
510
427
|
self.mask = None
|
|
428
|
+
self.reciprocal_lattice_params = None
|
|
429
|
+
self.lattice_params = None
|
|
511
430
|
self.a, self.b, self.c, self.al, self.be, self.ga = [None] * 6
|
|
431
|
+
self.a_star, self.b_star, self.c_star, self.al_star, self.be_star, self.ga_star = [None] * 6
|
|
512
432
|
|
|
513
433
|
def set_data(self, data):
|
|
514
434
|
self.data = data
|
|
435
|
+
if self.mask is None:
|
|
436
|
+
self.mask = np.zeros(data[data.signal].nxdata.shape)
|
|
437
|
+
self.H, self.K, self.L = np.meshgrid(data[data.axes[0]], data[data.axes[1]], data[data.axes[2]], indexing='ij')
|
|
515
438
|
|
|
516
439
|
def set_lattice_params(self, lattice_params):
|
|
517
440
|
self.a, self.b, self.c, self.al, self.be, self.ga = lattice_params
|
|
@@ -519,53 +442,18 @@ class Puncher:
|
|
|
519
442
|
self.reciprocal_lattice_params = reciprocal_lattice_params(lattice_params)
|
|
520
443
|
self.a_star, self.b_star, self.c_star, self.al_star, self.be_star, self.ga_star = self.reciprocal_lattice_params
|
|
521
444
|
|
|
445
|
+
def add_mask(self, maskaddition):
|
|
446
|
+
self.mask = np.logical_or(self.mask, maskaddition)
|
|
522
447
|
|
|
523
|
-
def
|
|
524
|
-
|
|
525
|
-
coeffs = [1, 0, 1, 0, 1, 0]
|
|
526
|
-
data = self.data
|
|
527
|
-
self.background = generate_gaussian(data[data.axes[0]], data[data.axes[1]], data[data.axes[2]],
|
|
528
|
-
amp=amp, stddev=stddev, lattice_params=self.lattice_params,
|
|
529
|
-
coeffs=coeffs)
|
|
530
|
-
|
|
531
|
-
def plot_gaussian_background(self):
|
|
532
|
-
data = self.data
|
|
533
|
-
fig, axes = plt.subplots(1, 3)
|
|
534
|
-
# Plot the background and subtracted
|
|
535
|
-
plot_slice(self.background[:, :, len(data[data.axes[2]]) // 2], data[data.axes[0]], data[data.axes[1]],
|
|
536
|
-
ax=axes[0], skew_angle=self.ga_star)
|
|
537
|
-
plot_slice(self.background[:, len(data[data.axes[1]]) // 2, :],data[data.axes[0]], data[data.axes[2]],
|
|
538
|
-
ax=axes[1], skew_angle=self.be_star)
|
|
539
|
-
plot_slice(self.background[len(data[data.axes[0]]) // 2, :, :],data[data.axes[1]], data[data.axes[2]],
|
|
540
|
-
ax=axes[2], skew_angle=self.al_star)
|
|
541
|
-
plt.show()
|
|
542
|
-
return fig, axes
|
|
448
|
+
def subtract_mask(self, masksubtraction):
|
|
449
|
+
self.mask = np.logical_and(self.mask, np.logical_not(masksubtraction))
|
|
543
450
|
|
|
544
|
-
def
|
|
545
|
-
data = self.data
|
|
546
|
-
fig, axes = plt.subplots(1, 3, figsize=(10,3))
|
|
547
|
-
# Plot the background and subtracted
|
|
548
|
-
plot_slice(data[data.signal][:, :, 0.0] - self.background[:, :, len(data[data.axes[2]]) // 2],
|
|
549
|
-
data[data.axes[0]], data[data.axes[1]],
|
|
550
|
-
ax=axes[0], skew_angle=self.ga_star, **kwargs)
|
|
551
|
-
plot_slice(data[data.signal][:, 0.0, :] - self.background[:, len(data[data.axes[1]]) // 2, :],
|
|
552
|
-
data[data.axes[0]], data[data.axes[2]],
|
|
553
|
-
ax=axes[1], skew_angle=self.be_star, **kwargs)
|
|
554
|
-
plot_slice(data[data.signal][0.0, :, :] - self.background[len(data[data.axes[0]]) // 2, :, :],
|
|
555
|
-
data[data.axes[1]], data[data.axes[2]],
|
|
556
|
-
ax=axes[2], skew_angle=self.al_star, **kwargs)
|
|
557
|
-
plt.show()
|
|
558
|
-
return fig, axes
|
|
559
|
-
|
|
560
|
-
def generate_mask(self, punch_radius, coeffs=None, thresh=None):
|
|
451
|
+
def generate_bragg_mask(self, punch_radius, coeffs=None, thresh=None):
|
|
561
452
|
if coeffs is None:
|
|
562
453
|
coeffs = [1, 0, 1, 0, 1, 0]
|
|
563
454
|
data = self.data
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
a_, b_, c_, al_, be_, ga_ = reciprocal_lattice_params((a, b, c, al, be, ga))
|
|
567
|
-
|
|
568
|
-
H, K, L = np.meshgrid(data[data.axes[0]], data[data.axes[1]], data[data.axes[2]])
|
|
455
|
+
H, K, L = self.H, self.K, self.L
|
|
456
|
+
a_, b_, c_, al_, be_, ga_ = self.reciprocal_lattice_params
|
|
569
457
|
|
|
570
458
|
mask = (coeffs[0] * (H - np.rint(H)) ** 2 +
|
|
571
459
|
coeffs[1] * (b_ * a_ / (a_ ** 2)) * (H - np.rint(H)) * (K - np.rint(K)) +
|
|
@@ -577,19 +465,51 @@ class Puncher:
|
|
|
577
465
|
if thresh:
|
|
578
466
|
mask = np.logical_and(mask, data[data.signal] > thresh)
|
|
579
467
|
|
|
580
|
-
|
|
468
|
+
return mask
|
|
469
|
+
|
|
470
|
+
def generate_mask_at_coord(self, coordinate, punch_radius, coeffs=None, thresh=None):
|
|
471
|
+
if coeffs is None:
|
|
472
|
+
coeffs = [1, 0, 1, 0, 1, 0]
|
|
473
|
+
data = self.data
|
|
474
|
+
H, K, L = self.H, self.K, self.L
|
|
475
|
+
a_, b_, c_, al_, be_, ga_ = self.reciprocal_lattice_params
|
|
476
|
+
centerH, centerK, centerL = coordinate
|
|
477
|
+
mask = (coeffs[0] * (H - centerH) ** 2 +
|
|
478
|
+
coeffs[1] * (b_ * a_ / (a_ ** 2)) * (H - centerH) * (K - centerK) +
|
|
479
|
+
coeffs[2] * (b_ / a_) ** 2 * (K - centerK) ** 2 +
|
|
480
|
+
coeffs[3] * (b_ * c_ / (a_ ** 2)) * (K - centerK) * (L - centerL) +
|
|
481
|
+
coeffs[4] * (c_ / a_) ** 2 * (L - centerL) ** 2 +
|
|
482
|
+
coeffs[5] * (c_ * a_ / (a_ ** 2)) * (L - centerL) * (H - centerH)) < punch_radius ** 2
|
|
483
|
+
|
|
484
|
+
if thresh:
|
|
485
|
+
mask = np.logical_and(mask, data[data.signal] > thresh)
|
|
581
486
|
|
|
582
487
|
return mask
|
|
583
488
|
|
|
489
|
+
def punch(self):
|
|
490
|
+
data= self.data
|
|
491
|
+
self.punched = NXdata(NXfield(np.where(self.mask, np.nan, data[data.signal].nxdata), name=data.signal),
|
|
492
|
+
(data[data.axes[0]],data[data.axes[1]],data[data.axes[2]]))
|
|
493
|
+
return self.punched
|
|
584
494
|
|
|
585
495
|
|
|
586
496
|
# class Reducer():
|
|
587
497
|
# pass
|
|
588
498
|
#
|
|
589
499
|
#
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
500
|
+
|
|
501
|
+
class Interpolator():
|
|
502
|
+
def __init__(self):
|
|
503
|
+
self.data = None
|
|
504
|
+
|
|
505
|
+
def set_data(self, data):
|
|
506
|
+
self.data = data
|
|
507
|
+
|
|
508
|
+
def set_kernel(self, kernel):
|
|
509
|
+
self.kernel = kernel
|
|
510
|
+
|
|
511
|
+
def generate_gaussian_kernel(self, amp, stddev, coeffs=None):
|
|
512
|
+
pass
|
|
513
|
+
|
|
514
|
+
def interpolate(self):
|
|
515
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: nxs-analysis-tools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.25
|
|
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
|
|
@@ -42,27 +42,27 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
42
42
|
Requires-Python: >=3.7
|
|
43
43
|
Description-Content-Type: text/markdown
|
|
44
44
|
License-File: LICENSE
|
|
45
|
-
Requires-Dist: matplotlib
|
|
46
|
-
Requires-Dist: numpy
|
|
47
|
-
Requires-Dist: ipython
|
|
48
|
-
Requires-Dist: pandas
|
|
49
|
-
Requires-Dist: nexusformat
|
|
50
|
-
Requires-Dist: lmfit
|
|
45
|
+
Requires-Dist: matplotlib >=3.7.1
|
|
46
|
+
Requires-Dist: numpy >=1.24.3
|
|
47
|
+
Requires-Dist: ipython >=1.0.0
|
|
48
|
+
Requires-Dist: pandas >=2.0.2
|
|
49
|
+
Requires-Dist: nexusformat >=1.0.1
|
|
50
|
+
Requires-Dist: lmfit >=1.2.1
|
|
51
51
|
Provides-Extra: dev
|
|
52
|
-
Requires-Dist: build
|
|
53
|
-
Requires-Dist: furo
|
|
54
|
-
Requires-Dist: ipykernel
|
|
55
|
-
Requires-Dist: myst-nb
|
|
56
|
-
Requires-Dist: myst-parser
|
|
57
|
-
Requires-Dist: numpydoc
|
|
58
|
-
Requires-Dist: pandoc
|
|
59
|
-
Requires-Dist: pylint
|
|
60
|
-
Requires-Dist: pytest
|
|
61
|
-
Requires-Dist: sphinx
|
|
62
|
-
Requires-Dist: sphinx-autobuild
|
|
63
|
-
Requires-Dist: sphinx-copybutton
|
|
64
|
-
Requires-Dist: sphinxext-opengraph
|
|
65
|
-
Requires-Dist: twine
|
|
52
|
+
Requires-Dist: build >=0.8.0 ; extra == 'dev'
|
|
53
|
+
Requires-Dist: furo >=2022.6.21 ; extra == 'dev'
|
|
54
|
+
Requires-Dist: ipykernel >=6.9.1 ; extra == 'dev'
|
|
55
|
+
Requires-Dist: myst-nb >=0.16.0 ; extra == 'dev'
|
|
56
|
+
Requires-Dist: myst-parser >=0.18.0 ; extra == 'dev'
|
|
57
|
+
Requires-Dist: numpydoc >=1.4.0 ; extra == 'dev'
|
|
58
|
+
Requires-Dist: pandoc >=2.2 ; extra == 'dev'
|
|
59
|
+
Requires-Dist: pylint >=2.12.2 ; extra == 'dev'
|
|
60
|
+
Requires-Dist: pytest >=7.1.2 ; extra == 'dev'
|
|
61
|
+
Requires-Dist: sphinx >=5.0.2 ; extra == 'dev'
|
|
62
|
+
Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'dev'
|
|
63
|
+
Requires-Dist: sphinx-copybutton >=0.5.0 ; extra == 'dev'
|
|
64
|
+
Requires-Dist: sphinxext-opengraph >=0.6.3 ; extra == 'dev'
|
|
65
|
+
Requires-Dist: twine >=4.0.1 ; extra == 'dev'
|
|
66
66
|
|
|
67
67
|
# nxs-analysis-tools
|
|
68
68
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
_meta/__init__.py,sha256=7cJjLXTZ19DjCsiIgJYt59ddCxaAy7fKcbVw6mC6zNQ,351
|
|
2
|
+
nxs_analysis_tools/__init__.py,sha256=HAdFMaImTfd2nCP1XzeSwreAv-wK6CeJbTn92aDQ-Bc,490
|
|
3
|
+
nxs_analysis_tools/chess.py,sha256=tNWc5xiwEjdtVPq0FFm2dCP2xvtkuv4IkMLur7Qeqjs,14079
|
|
4
|
+
nxs_analysis_tools/datareduction.py,sha256=lBydXjACptm8WHlO3knZP-ridjorPuoW_sqe7Bip73s,32112
|
|
5
|
+
nxs_analysis_tools/fitting.py,sha256=f0wUn2uLwT6a2Yg8QgzzSdR0zgqjjeNMj-H_HJh7D6o,8888
|
|
6
|
+
nxs_analysis_tools/pairdistribution.py,sha256=-_ULgC1XA9UKposzk51-64Y3cPWqdnBNAK7sdVTGHXM,20972
|
|
7
|
+
nxs_analysis_tools-0.0.25.dist-info/LICENSE,sha256=tdnoYVH1-ogW_5-gGs9bK-IkCamH1ATJqrdL37kWTHk,1102
|
|
8
|
+
nxs_analysis_tools-0.0.25.dist-info/METADATA,sha256=2o3IJevdoU9hoWwkIMens_mXpWxNrJSdX2DXnLzysG8,3837
|
|
9
|
+
nxs_analysis_tools-0.0.25.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
10
|
+
nxs_analysis_tools-0.0.25.dist-info/top_level.txt,sha256=8U000GNPzo6T6pOMjRdgOSO5heMzLMGjkxa1CDtyMHM,25
|
|
11
|
+
nxs_analysis_tools-0.0.25.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
_meta/__init__.py,sha256=IfDXCuKvuNWLFdLhpE9vE-4teC25IyL7gxQBBKNmGS8,351
|
|
2
|
-
nxs_analysis_tools/__init__.py,sha256=76pZHRU38bcY1EENxK2CEfWJC_hcwU2KH8om_FTuPN0,462
|
|
3
|
-
nxs_analysis_tools/chess.py,sha256=tNWc5xiwEjdtVPq0FFm2dCP2xvtkuv4IkMLur7Qeqjs,14079
|
|
4
|
-
nxs_analysis_tools/datareduction.py,sha256=XGlAgKavKE_XNo5oABXydI8Xie7OmXOvrRUEgkI9WS4,22110
|
|
5
|
-
nxs_analysis_tools/fitting.py,sha256=f0wUn2uLwT6a2Yg8QgzzSdR0zgqjjeNMj-H_HJh7D6o,8888
|
|
6
|
-
nxs_analysis_tools/pairdistribution.py,sha256=3_Lyg0iuajzUmGppzs48pdGvcjpiDGCURn4bxPtoijY,23475
|
|
7
|
-
nxs_analysis_tools-0.0.23.dist-info/LICENSE,sha256=tdnoYVH1-ogW_5-gGs9bK-IkCamH1ATJqrdL37kWTHk,1102
|
|
8
|
-
nxs_analysis_tools-0.0.23.dist-info/METADATA,sha256=DFiPw9Jg1CMgd67TLcktZcTX4oMVPVwMEiKLJyKEXYI,3877
|
|
9
|
-
nxs_analysis_tools-0.0.23.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
10
|
-
nxs_analysis_tools-0.0.23.dist-info/top_level.txt,sha256=8U000GNPzo6T6pOMjRdgOSO5heMzLMGjkxa1CDtyMHM,25
|
|
11
|
-
nxs_analysis_tools-0.0.23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|