nxs-analysis-tools 0.1.5__tar.gz → 0.1.6__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.1.5 → nxs_analysis_tools-0.1.6}/PKG-INFO +1 -1
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/pyproject.toml +2 -2
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/_meta/__init__.py +1 -1
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/chess.py +105 -6
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/fitting.py +51 -9
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/LICENSE +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/MANIFEST.in +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/README.md +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/setup.cfg +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/setup.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/__init__.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/datareduction.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/pairdistribution.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools.egg-info/SOURCES.txt +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_accurate_highlight.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_chess.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_chess_fitting.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_datareduction.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_ellipsoidal_window.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_fitting.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_lmfit.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_mask_plotting.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_pairdistribution.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_plot_slice_axes_types.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_plot_slice_with_ndarray.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_rotate_data.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_sum_axis.py +0 -0
- {nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_symmetrizer_rectangular_plane.py +0 -0
|
@@ -6,7 +6,7 @@ build-backend = 'setuptools.build_meta'
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = 'nxs-analysis-tools'
|
|
9
|
-
version = '0.1.
|
|
9
|
+
version = '0.1.6'
|
|
10
10
|
description = 'Reduce and transform nexus format (.nxs) scattering data.'
|
|
11
11
|
readme = 'README.md'
|
|
12
12
|
requires-python = '>=3.7'
|
|
@@ -71,7 +71,7 @@ dev = [
|
|
|
71
71
|
'DOI' = 'https://doi.org/10.5281/zenodo.15186359'
|
|
72
72
|
|
|
73
73
|
[tool.bumpver]
|
|
74
|
-
current_version = "0.1.
|
|
74
|
+
current_version = "0.1.6"
|
|
75
75
|
version_pattern = "MAJOR.MINOR.PATCH[-TAG]"
|
|
76
76
|
tag_pattern = "vMAJOR.MINOR.PATCH[-TAG]"
|
|
77
77
|
commit_message = "Bump version {old_version} -> {new_version}"
|
|
@@ -14,6 +14,7 @@ from IPython.display import display, Markdown
|
|
|
14
14
|
from nxs_analysis_tools import load_data, Scissors
|
|
15
15
|
from nxs_analysis_tools.fitting import LinecutModel
|
|
16
16
|
from nxs_analysis_tools.datareduction import load_transform, reciprocal_lattice_params
|
|
17
|
+
from lmfit.models import PseudoVoigtModel, LinearModel
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class TempDependence:
|
|
@@ -98,7 +99,11 @@ class TempDependence:
|
|
|
98
99
|
Fit the line cut models for each temperature.
|
|
99
100
|
plot_fit(mdheadings=False, **kwargs):
|
|
100
101
|
Plot the fit results for each temperature.
|
|
101
|
-
|
|
102
|
+
overlay_fits(numpoints=None, vertical_offset=0, cmap='viridis', ax=ax):
|
|
103
|
+
Plot raw data and fitted models for each temperature.
|
|
104
|
+
fit_peak_simple():
|
|
105
|
+
Perform a basic fit using a pseudo-Voigt peak shape, linear background, and no constraints.
|
|
106
|
+
plot_order_parameter():
|
|
102
107
|
Plot the temperature dependence of the peakheight parameter.
|
|
103
108
|
print_fit_report():
|
|
104
109
|
Print the fit report for each temperature.
|
|
@@ -469,7 +474,7 @@ class TempDependence:
|
|
|
469
474
|
y = np.array([int(t) for t in self.temperatures])
|
|
470
475
|
|
|
471
476
|
# Collect counts from each temperature and ensure they are numpy arrays
|
|
472
|
-
v = [self.linecuts[T].
|
|
477
|
+
v = [self.linecuts[T].nxsignal.nxdata for T in self.temperatures]
|
|
473
478
|
|
|
474
479
|
# Convert list of arrays to a 2D array for the heatmap
|
|
475
480
|
v_2d = np.array(v)
|
|
@@ -548,7 +553,7 @@ class TempDependence:
|
|
|
548
553
|
|
|
549
554
|
Parameters
|
|
550
555
|
----------
|
|
551
|
-
model_components : Model or iterable of Model
|
|
556
|
+
model_components : Model, CompositeModel, or iterable of Model
|
|
552
557
|
The model components to set for all line cut models.
|
|
553
558
|
|
|
554
559
|
"""
|
|
@@ -561,7 +566,8 @@ class TempDependence:
|
|
|
561
566
|
|
|
562
567
|
This method sets the parameter hints for all line cut models in the analysis.
|
|
563
568
|
It iterates over each line cut model and calls their respective `set_param_hint` method
|
|
564
|
-
with the provided arguments and keyword arguments.
|
|
569
|
+
with the provided arguments and keyword arguments. These are implemented when the
|
|
570
|
+
.make_params() method is called.
|
|
565
571
|
|
|
566
572
|
Parameters
|
|
567
573
|
----------
|
|
@@ -573,10 +579,40 @@ class TempDependence:
|
|
|
573
579
|
"""
|
|
574
580
|
[linecutmodel.set_param_hint(*args, **kwargs)
|
|
575
581
|
for linecutmodel in self.linecutmodels.values()]
|
|
582
|
+
|
|
583
|
+
def params_set(self, name, **kwargs):
|
|
584
|
+
"""
|
|
585
|
+
Set constraints on a parameter for all line cut models.
|
|
586
|
+
|
|
587
|
+
This method updates the specified parameter across all models in
|
|
588
|
+
`self.linecutmodels` using the keyword arguments provided. These
|
|
589
|
+
keyword arguments are passed to the `set()` method of the parameter,
|
|
590
|
+
which comes from a `lmfit.Parameters` object.
|
|
591
|
+
|
|
592
|
+
Parameters
|
|
593
|
+
----------
|
|
594
|
+
name : str
|
|
595
|
+
Name of the parameter to modify (must exist in each model).
|
|
596
|
+
**kwargs
|
|
597
|
+
Constraint arguments passed to `Parameter.set()`, such as `value`,
|
|
598
|
+
`min`, `max`, `vary`, etc.
|
|
599
|
+
|
|
600
|
+
Raises
|
|
601
|
+
------
|
|
602
|
+
KeyError
|
|
603
|
+
If the parameter `name` does not exist in one of the models.
|
|
604
|
+
|
|
605
|
+
Example
|
|
606
|
+
-------
|
|
607
|
+
>>> sample.params_set('peakamplitude', value=5, min=0, vary=True)
|
|
608
|
+
"""
|
|
609
|
+
|
|
610
|
+
for linecutmodel in self.linecutmodels.values():
|
|
611
|
+
linecutmodel.params[name].set(**kwargs)
|
|
576
612
|
|
|
577
613
|
def make_params(self):
|
|
578
614
|
"""
|
|
579
|
-
|
|
615
|
+
Create and initialize the parameters for all models.
|
|
580
616
|
|
|
581
617
|
This method creates the parameters for all line cut models in the analysis.
|
|
582
618
|
It iterates over each line cut model and calls their respective `make_params` method.
|
|
@@ -585,7 +621,8 @@ class TempDependence:
|
|
|
585
621
|
|
|
586
622
|
def guess(self):
|
|
587
623
|
"""
|
|
588
|
-
Make initial parameter guesses for all line cut models.
|
|
624
|
+
Make initial parameter guesses for all line cut models. This overwrites any prior initial
|
|
625
|
+
values and constraints.
|
|
589
626
|
|
|
590
627
|
This method generates initial parameter guesses for all line cut models in the analysis.
|
|
591
628
|
It iterates over each line cut model and calls their respective `guess` method.
|
|
@@ -657,6 +694,68 @@ class TempDependence:
|
|
|
657
694
|
title=f"{T} K",
|
|
658
695
|
**kwargs)
|
|
659
696
|
|
|
697
|
+
def overlay_fits(self, numpoints=None, vertical_offset=0, cmap='viridis', ax=None):
|
|
698
|
+
"""
|
|
699
|
+
Plot raw data and fitted models for each temperature with optional vertical offsets.
|
|
700
|
+
|
|
701
|
+
Parameters:
|
|
702
|
+
-----------
|
|
703
|
+
numpoints : int or None, default=None
|
|
704
|
+
Number of points to evaluate for the fitted model curves.
|
|
705
|
+
If None, uses the number of raw data points for each linecut.
|
|
706
|
+
vertical_offset : float, default=0
|
|
707
|
+
Amount to vertically offset each linecut for clarity.
|
|
708
|
+
cmap : str, default='viridis'
|
|
709
|
+
Name of the matplotlib colormap used to distinguish different temperatures.
|
|
710
|
+
ax : matplotlib.axes.Axes or None, default=None
|
|
711
|
+
Axis object to plot on. If None, a new figure and axis are created.
|
|
712
|
+
|
|
713
|
+
The function:
|
|
714
|
+
- Uses a colormap to assign unique colors to each temperature.
|
|
715
|
+
- Plots raw data alongside evaluated fit models for each linecut.
|
|
716
|
+
- Vertically offsets each trace by a constant value for visual separation.
|
|
717
|
+
- Displays a legend in reverse order to match top-to-bottom visual stacking.
|
|
718
|
+
- Automatically labels the x- and y-axes based on NeXus-style data metadata.
|
|
719
|
+
"""
|
|
720
|
+
|
|
721
|
+
# Create a figure and axes if an axis is not already provided
|
|
722
|
+
_, ax = plt.subplots() if ax is None else (None, ax)
|
|
723
|
+
|
|
724
|
+
# Generate a color palette for the various temperatures
|
|
725
|
+
cmap = plt.get_cmap(cmap)
|
|
726
|
+
colors = [cmap(i / len(self.temperatures)) for i, _ in enumerate(self.temperatures)]
|
|
727
|
+
|
|
728
|
+
for i, lm in enumerate(self.linecutmodels.values()):
|
|
729
|
+
# Plot the raw data
|
|
730
|
+
ax.plot(lm.x, lm.y + vertical_offset * i, '.', c=colors[i])
|
|
731
|
+
|
|
732
|
+
# Evaluate the fit
|
|
733
|
+
numpoints = len(lm.x) if numpoints is None else numpoints
|
|
734
|
+
x_eval = np.linspace(lm.x.min(), lm.x.max(), numpoints)
|
|
735
|
+
y_eval = lm.modelresult.eval(x=x_eval)
|
|
736
|
+
ax.plot(x_eval, y_eval + vertical_offset * i, '-', c=colors[i], label=self.temperatures[i])
|
|
737
|
+
|
|
738
|
+
# Reverse legend entries to match top-to-bottom stacking
|
|
739
|
+
handles, labels = ax.get_legend_handles_labels()
|
|
740
|
+
ax.legend(handles[::-1], labels[::-1])
|
|
741
|
+
|
|
742
|
+
# Add axis labels
|
|
743
|
+
ax.set(xlabel=lm.data.nxaxes[0].nxname, ylabel=lm.data.nxsignal.nxname)
|
|
744
|
+
|
|
745
|
+
def fit_peak_simple(self):
|
|
746
|
+
"""
|
|
747
|
+
Fit all linecuts in the temperature series using a pseudo-Voigt peak shape and linear
|
|
748
|
+
background, with no constraints.
|
|
749
|
+
"""
|
|
750
|
+
|
|
751
|
+
for T in self.temperatures:
|
|
752
|
+
linecutmodel = self.linecutmodels[T]
|
|
753
|
+
linecutmodel.set_model_components([PseudoVoigtModel(prefix='peak'),
|
|
754
|
+
LinearModel(prefix='background')])
|
|
755
|
+
linecutmodel.make_params()
|
|
756
|
+
linecutmodel.guess()
|
|
757
|
+
linecutmodel.fit()
|
|
758
|
+
|
|
660
759
|
def plot_order_parameter(self):
|
|
661
760
|
"""
|
|
662
761
|
Plot the temperature dependence of the peak height (order parameter).
|
|
@@ -3,8 +3,9 @@ Module for fitting of linecuts using the lmfit package.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import operator
|
|
6
|
-
from lmfit
|
|
7
|
-
from lmfit.model import CompositeModel
|
|
6
|
+
from lmfit import Parameters
|
|
7
|
+
from lmfit.model import Model, CompositeModel
|
|
8
|
+
from lmfit.models import PseudoVoigtModel, LinearModel
|
|
8
9
|
import matplotlib.pyplot as plt
|
|
9
10
|
import numpy as np
|
|
10
11
|
|
|
@@ -66,6 +67,8 @@ class LinecutModel:
|
|
|
66
67
|
Fit the model to the data.
|
|
67
68
|
plot_fit(self, numpoints=None, fit_report=True, **kwargs)
|
|
68
69
|
Plot the fitted model.
|
|
70
|
+
fit_peak_simple():
|
|
71
|
+
Perform a basic fit using a pseudo-Voigt peak shape, linear background, and no constraints.
|
|
69
72
|
print_fit_report(self)
|
|
70
73
|
Print the fit report.
|
|
71
74
|
"""
|
|
@@ -110,15 +113,25 @@ class LinecutModel:
|
|
|
110
113
|
|
|
111
114
|
Parameters
|
|
112
115
|
----------
|
|
113
|
-
model_components : Model or
|
|
114
|
-
The model component(s) to be used for fitting
|
|
115
|
-
which will be combined into a CompositeModel.
|
|
116
|
+
model_components : Model, CompositeModel, or iterable of Model
|
|
117
|
+
The model component(s) to be used for fitting.
|
|
116
118
|
"""
|
|
117
119
|
|
|
118
120
|
# If the model only has one component, then use it as the model
|
|
119
121
|
if isinstance(model_components, Model):
|
|
120
122
|
self.model = model_components
|
|
121
|
-
|
|
123
|
+
self.params = self.model.make_params()
|
|
124
|
+
|
|
125
|
+
# If the model is a composite model, then use it as the model
|
|
126
|
+
elif isinstance(model_components, CompositeModel):
|
|
127
|
+
self.model = model_components
|
|
128
|
+
self.model_components = self.model.components
|
|
129
|
+
# Make params for each component of the model
|
|
130
|
+
self.params = Parameters()
|
|
131
|
+
for component in self.model.components:
|
|
132
|
+
self.params.update(component.make_params())
|
|
133
|
+
|
|
134
|
+
# Else, combine the components into a composite model and use that as the model
|
|
122
135
|
else:
|
|
123
136
|
self.model_components = model_components
|
|
124
137
|
self.model = model_components[0]
|
|
@@ -127,9 +140,15 @@ class LinecutModel:
|
|
|
127
140
|
for component in model_components[1:]:
|
|
128
141
|
self.model = CompositeModel(self.model, component, operator.add)
|
|
129
142
|
|
|
143
|
+
# Make params for each component of the model
|
|
144
|
+
self.params = Parameters()
|
|
145
|
+
for component in self.model.components:
|
|
146
|
+
self.params.update(component.make_params())
|
|
147
|
+
|
|
130
148
|
def set_param_hint(self, *args, **kwargs):
|
|
131
149
|
"""
|
|
132
|
-
Set parameter hints for the model.
|
|
150
|
+
Set parameter hints for the model. These are implemented when the .make_params() method
|
|
151
|
+
is called.
|
|
133
152
|
|
|
134
153
|
Parameters
|
|
135
154
|
----------
|
|
@@ -159,10 +178,22 @@ class LinecutModel:
|
|
|
159
178
|
|
|
160
179
|
def guess(self):
|
|
161
180
|
"""
|
|
162
|
-
Perform initial guesses for each model component.
|
|
181
|
+
Perform initial guesses for each model component and update params. This overwrites any
|
|
182
|
+
prior initial values and constraints.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
components_params : list
|
|
187
|
+
A list containing params objects for each component of the model.
|
|
163
188
|
"""
|
|
164
|
-
|
|
189
|
+
|
|
190
|
+
components_params = []
|
|
191
|
+
|
|
192
|
+
for model_component in self.model.components:
|
|
165
193
|
self.params.update(model_component.guess(self.y, x=self.x))
|
|
194
|
+
components_params.append(model_component.guess(self.y, x=self.x))
|
|
195
|
+
|
|
196
|
+
return components_params
|
|
166
197
|
|
|
167
198
|
def print_initial_params(self):
|
|
168
199
|
"""
|
|
@@ -251,6 +282,17 @@ class LinecutModel:
|
|
|
251
282
|
if fit_report:
|
|
252
283
|
print(self.modelresult.fit_report())
|
|
253
284
|
return ax
|
|
285
|
+
|
|
286
|
+
def fit_peak_simple(self):
|
|
287
|
+
"""
|
|
288
|
+
Fit all linecuts in the temperature series using a pseudo-Voigt peak shape and linear
|
|
289
|
+
background, with no constraints.
|
|
290
|
+
"""
|
|
291
|
+
self.set_model_components([PseudoVoigtModel(prefix='peak'),
|
|
292
|
+
LinearModel(prefix='background')])
|
|
293
|
+
self.make_params()
|
|
294
|
+
self.guess()
|
|
295
|
+
self.fit()
|
|
254
296
|
|
|
255
297
|
def print_fit_report(self):
|
|
256
298
|
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/datareduction.py
RENAMED
|
File without changes
|
{nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools/pairdistribution.py
RENAMED
|
File without changes
|
{nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/src/nxs_analysis_tools.egg-info/SOURCES.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nxs_analysis_tools-0.1.5 → nxs_analysis_tools-0.1.6}/tests/test_symmetrizer_rectangular_plane.py
RENAMED
|
File without changes
|