nxs-analysis-tools 0.0.45__tar.gz → 0.0.46__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.

Files changed (27) hide show
  1. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/LICENSE +1 -1
  2. {nxs_analysis_tools-0.0.45/src/nxs_analysis_tools.egg-info → nxs_analysis_tools-0.0.46}/PKG-INFO +2 -2
  3. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/pyproject.toml +1 -1
  4. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/_meta/__init__.py +2 -2
  5. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools/chess.py +54 -12
  6. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools/datareduction.py +24 -8
  7. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools/pairdistribution.py +83 -38
  8. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46/src/nxs_analysis_tools.egg-info}/PKG-INFO +2 -2
  9. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/MANIFEST.in +0 -0
  10. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/README.md +0 -0
  11. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/setup.cfg +0 -0
  12. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/setup.py +0 -0
  13. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools/__init__.py +0 -0
  14. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools/fitting.py +0 -0
  15. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools.egg-info/SOURCES.txt +0 -0
  16. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools.egg-info/dependency_links.txt +0 -0
  17. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools.egg-info/requires.txt +0 -0
  18. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/src/nxs_analysis_tools.egg-info/top_level.txt +0 -0
  19. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_chess.py +0 -0
  20. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_chess_fitting.py +0 -0
  21. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_datareduction.py +0 -0
  22. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_fitting.py +0 -0
  23. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_lmfit.py +0 -0
  24. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_mask_plotting.py +0 -0
  25. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_pairdistribution.py +0 -0
  26. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_plot_slice_with_ndarray.py +0 -0
  27. {nxs_analysis_tools-0.0.45 → nxs_analysis_tools-0.0.46}/tests/test_symmetrizer_rectangular_plane.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Steven J. Gomez Alvarado
3
+ Copyright (c) 2023-2025 Steven J. Gomez Alvarado
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nxs-analysis-tools
3
- Version: 0.0.45
3
+ Version: 0.0.46
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
7
7
 
8
- Copyright (c) 2023 Steven J. Gomez Alvarado
8
+ Copyright (c) 2023-2025 Steven J. Gomez Alvarado
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  of this software and associated documentation files (the "Software"), to deal
@@ -6,7 +6,7 @@ build-backend = 'setuptools.build_meta'
6
6
 
7
7
  [project]
8
8
  name = 'nxs-analysis-tools'
9
- version = '0.0.45'
9
+ version = '0.0.46'
10
10
  description = 'Reduce and transform nexus format (.nxs) scattering data.'
11
11
  readme = 'README.md'
12
12
  requires-python = '>=3.7'
@@ -4,7 +4,7 @@
4
4
  __project__ = 'nxs-analysis-tools'
5
5
  __author__ = 'Steven J. Gomez Alvarado'
6
6
  __email__ = 'stevenjgomez@ucsb.edu'
7
- __copyright__ = f"2023, {__author__}"
7
+ __copyright__ = f"2023-2025, {__author__}"
8
8
  __license__ = 'MIT'
9
- __version__ = '0.0.45'
9
+ __version__ = '0.0.46'
10
10
  __repo_url__ = 'https://github.com/stevenjgomez/nxs_analysis_tools'
@@ -58,9 +58,9 @@ class TempDependence:
58
58
  Initialize Scissors and LinecutModel objects for each temperature.
59
59
  set_data(temperature, data):
60
60
  Set the dataset for a specific temperature.
61
- load_transforms(temperatures_list=None):
61
+ load_transforms(temperatures_list=None, print_tree=True):
62
62
  Load transform datasets (from nxrefine) based on temperature.
63
- load_datasets(file_ending='hkli.nxs', temperatures_list=None):
63
+ load_datasets(file_ending='hkli.nxs', temperatures_list=None, print_tree=True):
64
64
  Load datasets (CHESS format) from the specified folder.
65
65
  get_sample_directory():
66
66
  Get the folder path where the datasets are located.
@@ -98,6 +98,8 @@ class TempDependence:
98
98
  Fit the line cut models for each temperature.
99
99
  plot_fit(mdheadings=False, **kwargs):
100
100
  Plot the fit results for each temperature.
101
+ plot_order_parameter(self):
102
+ Plot the temperature dependence of the peakheight parameter.
101
103
  print_fit_report():
102
104
  Print the fit report for each temperature.
103
105
  """
@@ -186,7 +188,7 @@ class TempDependence:
186
188
  """
187
189
  self.datasets[temperature] = data
188
190
 
189
- def load_transforms(self, temperatures_list=None):
191
+ def load_transforms(self, temperatures_list=None, print_tree=True):
190
192
  """
191
193
  Load transform datasets (from nxrefine) based on temperature.
192
194
 
@@ -194,6 +196,8 @@ class TempDependence:
194
196
  ----------
195
197
  temperatures_list : list of int or None, optional
196
198
  List of temperatures to load. If None, all available temperatures are loaded.
199
+ print_tree : bool, optional
200
+ Whether to print the data tree upon loading. Default True.
197
201
  """
198
202
  # Convert all temperatures to strings
199
203
  if temperatures_list:
@@ -231,7 +235,7 @@ class TempDependence:
231
235
 
232
236
  # Save dataset
233
237
  try:
234
- self.datasets[self.temperatures[i]] = load_transform(path)
238
+ self.datasets[self.temperatures[i]] = load_transform(path, print_tree)
235
239
  except Exception as e:
236
240
  # Report temperature that was unable to load, then raise exception.
237
241
  temp_failed = self.temperatures[i]
@@ -245,7 +249,7 @@ class TempDependence:
245
249
  # Initialize linecutmodel object
246
250
  self.linecutmodels[self.temperatures[i]] = LinecutModel()
247
251
 
248
- def load_datasets(self, file_ending='hkli.nxs', temperatures_list=None):
252
+ def load_datasets(self, file_ending='hkli.nxs', temperatures_list=None, print_tree=True):
249
253
  """
250
254
  Load datasets (CHESS format) from the specified folder.
251
255
 
@@ -256,6 +260,8 @@ class TempDependence:
256
260
  temperatures_list : list of int or None, optional
257
261
  The list of specific temperatures to load. If None, all available temperatures are
258
262
  loaded. The default is None.
263
+ print_tree : bool, optional
264
+ Whether to print the data tree upon loading. Default True.
259
265
  """
260
266
  temperature_folders = [] # Empty list to store temperature folder names
261
267
  for item in os.listdir(self.sample_directory):
@@ -278,7 +284,7 @@ class TempDependence:
278
284
  filepath = os.path.join(self.sample_directory, T, file)
279
285
 
280
286
  # Load dataset at each temperature
281
- self.datasets[T] = load_data(filepath)
287
+ self.datasets[T] = load_data(filepath, print_tree)
282
288
 
283
289
  # Initialize scissors object at each temperature
284
290
  self.scissors[T] = Scissors()
@@ -370,15 +376,13 @@ class TempDependence:
370
376
  A dictionary of linecuts obtained from the cutting operation.
371
377
  """
372
378
 
373
- center = center if center is not None else self.scissors[self.temperatures[0]].center
374
- window = window if window is not None else self.scissors[self.temperatures[0]].window
375
- axis = axis if axis is not None else self.scissors[self.temperatures[0]].axis
376
-
377
379
  for T in self.temperatures:
378
380
  if verbose:
379
381
  print("-------------------------------")
380
382
  print("Cutting T = " + T + " K data...")
381
- self.scissors[T].cut_data(center, window, axis, verbose)
383
+ self.scissors[T].set_center(center)
384
+ self.scissors[T].set_window(window)
385
+ self.scissors[T].cut_data(axis=axis, verbose=verbose)
382
386
  self.linecuts[T] = self.scissors[T].linecut
383
387
  self.linecutmodels[T].set_data(self.linecuts[T])
384
388
 
@@ -466,7 +470,7 @@ class TempDependence:
466
470
  _, ax = plt.subplots()
467
471
  p = ax.pcolormesh(X, Y, v_2d, **kwargs)
468
472
  plt.colorbar(p, label='counts')
469
- ax.set(xlabel=cut.axes, ylabel=r'$T$ (K)')
473
+ ax.set(xlabel=self.xlabel, ylabel=r'$T$ (K)')
470
474
 
471
475
  return p
472
476
 
@@ -641,6 +645,44 @@ class TempDependence:
641
645
  title=f"{T} K",
642
646
  **kwargs)
643
647
 
648
+ def plot_order_parameter(self):
649
+ """
650
+ Plot the temperature dependence of the peak height (order parameter).
651
+
652
+ This method extracts the peak height from each temperature-dependent
653
+ line cut fit stored in `linecutmodels` and plots it as a function
654
+ of temperature using matplotlib.
655
+
656
+ Returns
657
+ -------
658
+ Figure
659
+ Matplotlib Figure object containing the peak height vs. temperature plot.
660
+ Axes
661
+ Matplotlib Axes object associated with the figure.
662
+
663
+ Notes
664
+ -----
665
+ - Temperature values are converted to integers for plotting.
666
+ - Peak heights are extracted from the 'peakheight' parameter in the model results.
667
+ - The plot uses standard axes labels with temperature in Kelvin.
668
+ """
669
+
670
+ # Create an array of temperature values
671
+ temperatures = [int(T) for T in self.temperatures]
672
+
673
+ # Create an empty list for the peak heights
674
+ peakheights = []
675
+
676
+ # Extract the peakheight at every temperature
677
+ for T in self.temperatures:
678
+ peakheights.append(self.linecutmodels[T].modelresult.params['peakheight'].value)
679
+
680
+ # Plot the peakheights vs. temperature
681
+ fig, ax = plt.subplots()
682
+ ax.plot(temperatures, peakheights)
683
+ ax.set(xlabel='$T$ (K)', ylabel='peakheight')
684
+ return fig, ax
685
+
644
686
  def print_fit_report(self):
645
687
  """
646
688
  Plot the fit results.
@@ -19,7 +19,7 @@ __all__ = ['load_data', 'load_transform', 'plot_slice', 'Scissors',
19
19
  'array_to_nxdata', 'Padder']
20
20
 
21
21
 
22
- def load_data(path):
22
+ def load_data(path, print_tree=True):
23
23
  """
24
24
  Load data from a NeXus file at a specified path. It is assumed that the data follows the CHESS
25
25
  file structure (i.e., root/entry/data/counts, etc.).
@@ -29,6 +29,9 @@ def load_data(path):
29
29
  path : str
30
30
  The path to the NeXus data file.
31
31
 
32
+ print_tree : bool, optional
33
+ Whether to print the data tree upon loading. Default True.
34
+
32
35
  Returns
33
36
  -------
34
37
  data : nxdata object
@@ -38,31 +41,42 @@ def load_data(path):
38
41
 
39
42
  g = nxload(path)
40
43
  try:
41
- print(g.entry.data.tree)
44
+ print(g.entry.data.tree) if print_tree else None
42
45
  except NeXusError:
43
46
  pass
44
47
 
45
48
  return g.entry.data
46
49
 
47
50
 
48
- def load_transform(path):
51
+ def load_transform(path, print_tree=True):
49
52
  """
50
53
  Load data obtained from nxrefine output from a specified path.
51
54
 
52
55
  Parameters
53
56
  ----------
54
- path : str The path to the transform data file.
57
+ path : str
58
+ The path to the transform data file.
59
+
60
+ print_tree : bool, optional
61
+ Whether to print the data tree upon loading. Default True.
55
62
 
56
63
  Returns
57
64
  -------
58
- data : nxdata object The loaded data stored in a nxdata object.
65
+ data : nxdata object
66
+ The loaded data stored in a nxdata object.
59
67
  """
68
+
60
69
  g = nxload(path)
61
- return NXdata(NXfield(g.entry.transform.data.nxdata.transpose(2, 1, 0), name='counts'),
70
+
71
+ data = NXdata(NXfield(g.entry.transform.data.nxdata.transpose(2, 1, 0), name='counts'),
62
72
  (g.entry.transform.Qh, g.entry.transform.Qk, g.entry.transform.Ql))
63
73
 
74
+ print(data.tree) if print_tree else None
75
+
76
+ return data
77
+
64
78
 
65
- def array_to_nxdata(array, data_template, signal_name='counts'):
79
+ def array_to_nxdata(array, data_template, signal_name=None):
66
80
  """
67
81
  Create an NXdata object from an input array and an NXdata template,
68
82
  with an optional signal name.
@@ -78,7 +92,7 @@ def array_to_nxdata(array, data_template, signal_name='counts'):
78
92
 
79
93
  signal_name : str, optional
80
94
  The name of the signal within the NXdata object. If not provided,
81
- the default signal name 'counts' is used.
95
+ the signal name is inherited from the data_template.
82
96
 
83
97
  Returns
84
98
  -------
@@ -87,6 +101,8 @@ def array_to_nxdata(array, data_template, signal_name='counts'):
87
101
  based on the template.
88
102
  """
89
103
  d = data_template
104
+ if signal_name is None:
105
+ signal_name = d.signal
90
106
  return NXdata(NXfield(array, name=signal_name),
91
107
  tuple(d[d.axes[i]] for i in range(len(d.axes))))
92
108
 
@@ -458,20 +458,35 @@ class Symmetrizer3D:
458
458
  self.a_star, self.b_star, self.c_star, \
459
459
  self.al_star, self.be_star, self.ga_star = self.reciprocal_lattice_params
460
460
 
461
- def symmetrize(self):
461
+ def symmetrize(self, positive_values=True):
462
462
  """
463
- Perform the symmetrization of the 3D dataset by sequentially applying
464
- 2D symmetrization on the three principal planes.
463
+ Symmetrize the 3D dataset by sequentially applying 2D symmetrization
464
+ on the three principal planes.
465
465
 
466
- This method symmetrizes the dataset on the three principal planes
467
- (q1-q2, q1-q3, q2-q3) and handles any negative values that might result
468
- from the symmetrization process.
466
+ This method performs symmetrization along the (q1-q2), (q1-q3),
467
+ and (q2-q3) planes, ensuring that the dataset maintains expected
468
+ symmetry properties. Optionally, negative values resulting from the
469
+ symmetrization process can be set to zero.
470
+
471
+ Parameters
472
+ ----------
473
+ positive_values : bool, optional
474
+ If True, sets negative symmetrized values to zero (default is True).
469
475
 
470
476
  Returns
471
477
  -------
472
- symmetrized : NXdata
473
- The symmetrized 3D dataset.
478
+ NXdata
479
+ The symmetrized 3D dataset stored in the `symmetrized` attribute.
480
+
481
+ Notes
482
+ -----
483
+ - Symmetrization is performed sequentially across three principal
484
+ planes using corresponding 2D symmetrization methods.
485
+ - The process prints progress updates and timing information.
486
+ - If `theta_max` is not set for a particular plane symmetrizer,
487
+ that plane is skipped.
474
488
  """
489
+
475
490
  starttime = time.time()
476
491
  data = self.data
477
492
  q1, q2, q3 = self.q1, self.q2, self.q3
@@ -480,7 +495,8 @@ class Symmetrizer3D:
480
495
  if self.plane1symmetrizer.theta_max is not None:
481
496
  print('Symmetrizing ' + self.plane1 + ' planes...')
482
497
  for k, value in enumerate(q3):
483
- print(f'Symmetrizing {q3.nxname}={value:.02f}...', end='\r')
498
+ print(f'Symmetrizing {q3.nxname}={value:.02f}.'
499
+ f'..', end='\r')
484
500
  data_symmetrized = self.plane1symmetrizer.symmetrize_2d(data[:, :, k])
485
501
  out_array[:, :, k] = data_symmetrized[data.signal].nxdata
486
502
  print('\nSymmetrized ' + self.plane1 + ' planes.')
@@ -505,7 +521,8 @@ class Symmetrizer3D:
505
521
  out_array[i, :, :] = data_symmetrized[data.signal].nxdata
506
522
  print('\nSymmetrized ' + self.plane3 + ' planes.')
507
523
 
508
- out_array[out_array < 0] = 0
524
+ if positive_values:
525
+ out_array[out_array < 0] = 0
509
526
 
510
527
  stoptime = time.time()
511
528
  print(f"\nSymmetrization finished in {((stoptime - starttime) / 60):.02f} minutes.")
@@ -1032,15 +1049,28 @@ class Interpolator:
1032
1049
  """
1033
1050
  self.kernel = kernel
1034
1051
 
1035
- def interpolate(self):
1052
+ def interpolate(self, verbose=True, positive_values=True):
1036
1053
  """
1037
1054
  Perform interpolation on the dataset using the specified kernel.
1038
1055
 
1039
- The interpolation is done by convolving the data with the kernel
1040
- using the `convolve_fft` function. Updates the `interpolated`
1041
- attribute with the result.
1056
+ This method convolves the dataset with a kernel using `convolve_fft`
1057
+ to perform interpolation. The resulting interpolated data is stored
1058
+ in the `interpolated` attribute.
1059
+
1060
+ Parameters
1061
+ ----------
1062
+ verbose : bool, optional
1063
+ If True, prints progress messages and timing information
1064
+ (default is True).
1065
+ positive_values : bool, optional
1066
+ If True, sets negative interpolated values to zero
1067
+ (default is True).
1042
1068
 
1043
- Prints the time taken for the interpolation process.
1069
+ Notes
1070
+ -----
1071
+ - The convolution operation is performed in Fourier space.
1072
+ - If a previous interpolation time is recorded, it is displayed
1073
+ before starting a new interpolation.
1044
1074
 
1045
1075
  Returns
1046
1076
  -------
@@ -1048,21 +1078,22 @@ class Interpolator:
1048
1078
  """
1049
1079
  start = time.time()
1050
1080
 
1051
- if self.interp_time:
1081
+ if self.interp_time and verbose:
1052
1082
  print(f"Last interpolation took {self.interp_time / 60:.2f} minutes.")
1053
1083
 
1054
- print("Running interpolation...")
1084
+ print("Running interpolation...") if verbose else None
1055
1085
  result = np.real(
1056
1086
  convolve_fft(self.data[self.data.signal].nxdata,
1057
1087
  self.kernel, allow_huge=True, return_fft=False))
1058
- print("Interpolation finished.")
1088
+ print("Interpolation finished.") if verbose else None
1059
1089
 
1060
1090
  end = time.time()
1061
1091
  interp_time = end - start
1062
1092
 
1063
- print(f'Interpolation took {interp_time / 60:.2f} minutes.')
1093
+ print(f'Interpolation took {interp_time / 60:.2f} minutes.') if verbose else None
1064
1094
 
1065
- result[result < 0] = 0
1095
+ if positive_values:
1096
+ result[result < 0] = 0
1066
1097
  self.interpolated = array_to_nxdata(result, self.data)
1067
1098
 
1068
1099
  def set_tukey_window(self, tukey_alphas=(1.0, 1.0, 1.0)):
@@ -1479,21 +1510,34 @@ class DeltaPDF:
1479
1510
  self.interpolator.set_kernel(kernel)
1480
1511
  self.kernel = kernel
1481
1512
 
1482
- def interpolate(self):
1513
+ def interpolate(self, verbose=True, positive_values=True):
1483
1514
  """
1484
1515
  Perform interpolation on the dataset using the specified kernel.
1485
1516
 
1486
- The interpolation is done by convolving the data with the kernel using
1487
- the `convolve_fft` function. Updates the `interpolated` attribute with
1488
- the result.
1517
+ This method convolves the dataset with a kernel using `convolve_fft`
1518
+ to perform interpolation. The resulting interpolated data is stored
1519
+ in the `interpolated` attribute.
1520
+
1521
+ Parameters
1522
+ ----------
1523
+ verbose : bool, optional
1524
+ If True, prints progress messages and timing information
1525
+ (default is True).
1526
+ positive_values : bool, optional
1527
+ If True, sets negative interpolated values to zero
1528
+ (default is True).
1489
1529
 
1490
- Prints the time taken for the interpolation process.
1530
+ Notes
1531
+ -----
1532
+ - The convolution operation is performed in Fourier space.
1533
+ - If a previous interpolation time is recorded, it is displayed
1534
+ before starting a new interpolation.
1491
1535
 
1492
1536
  Returns
1493
1537
  -------
1494
1538
  None
1495
1539
  """
1496
- self.interpolator.interpolate()
1540
+ self.interpolator.interpolate(verbose, positive_values)
1497
1541
  self.interpolated = self.interpolator.interpolated
1498
1542
 
1499
1543
  def set_tukey_window(self, tukey_alphas=(1.0, 1.0, 1.0)):
@@ -1578,14 +1622,16 @@ class DeltaPDF:
1578
1622
  """
1579
1623
  Perform a 3D Fourier Transform on the padded data.
1580
1624
 
1581
- This function applies an inverse Fourier Transform to the padded data
1582
- using the `pyfftw` library to optimize performance. The result is a
1583
- transformed array with spatial frequency components calculated along
1584
- each axis.
1625
+ This method applies an inverse Fourier Transform to the padded data
1626
+ using `pyfftw` for optimized performance. The result is stored in
1627
+ the `fft` attribute as an NXdata object containing the transformed
1628
+ spatial frequency components.
1585
1629
 
1586
1630
  Parameters
1587
1631
  ----------
1588
- None
1632
+ is_2d : bool, optional
1633
+ If True, performs the FFT only along the first two axes,
1634
+ skipping the out-of-plane direction (default is False).
1589
1635
 
1590
1636
  Returns
1591
1637
  -------
@@ -1593,13 +1639,12 @@ class DeltaPDF:
1593
1639
 
1594
1640
  Notes
1595
1641
  -----
1596
- - The FFT is performed in two stages: first along the last dimension of
1597
- the input array and then along the first two dimensions.
1598
- - The function uses `pyfftw` for efficient computation of the Fourier
1599
- Transform.
1600
- - The output frequency components are computed based on the step sizes
1601
- of the original data axes.
1602
-
1642
+ - Calls `fourier_transform_nxdata` to perform the transformation.
1643
+ - The FFT is computed in two stages: first along the last dimension,
1644
+ then along the first two dimensions.
1645
+ - The output includes frequency components computed from the step
1646
+ sizes of the original data axes.
1603
1647
 
1604
1648
  """
1649
+
1605
1650
  self.fft = fourier_transform_nxdata(self.padded, is_2d=is_2d)
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nxs-analysis-tools
3
- Version: 0.0.45
3
+ Version: 0.0.46
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
7
7
 
8
- Copyright (c) 2023 Steven J. Gomez Alvarado
8
+ Copyright (c) 2023-2025 Steven J. Gomez Alvarado
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  of this software and associated documentation files (the "Software"), to deal