pytme 0.3b0__cp311-cp311-macosx_15_0_arm64.whl → 0.3b0.post1__cp311-cp311-macosx_15_0_arm64.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.
Files changed (55) hide show
  1. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/estimate_memory_usage.py +1 -5
  2. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/match_template.py +163 -201
  3. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/postprocess.py +48 -39
  4. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocess.py +10 -23
  5. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocessor_gui.py +3 -4
  6. pytme-0.3b0.post1.data/scripts/pytme_runner.py +769 -0
  7. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/METADATA +14 -14
  8. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/RECORD +54 -50
  9. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/entry_points.txt +1 -0
  10. pytme-0.3b0.post1.dist-info/licenses/LICENSE +339 -0
  11. scripts/estimate_memory_usage.py +1 -5
  12. scripts/eval.py +93 -0
  13. scripts/match_template.py +163 -201
  14. scripts/match_template_filters.py +1200 -0
  15. scripts/postprocess.py +48 -39
  16. scripts/preprocess.py +10 -23
  17. scripts/preprocessor_gui.py +3 -4
  18. scripts/pytme_runner.py +769 -0
  19. scripts/refine_matches.py +0 -1
  20. tests/preprocessing/test_frequency_filters.py +19 -10
  21. tests/test_analyzer.py +122 -122
  22. tests/test_backends.py +1 -0
  23. tests/test_matching_cli.py +30 -30
  24. tests/test_matching_data.py +5 -5
  25. tests/test_matching_utils.py +1 -1
  26. tme/__version__.py +1 -1
  27. tme/analyzer/__init__.py +1 -1
  28. tme/analyzer/_utils.py +1 -4
  29. tme/analyzer/aggregation.py +15 -6
  30. tme/analyzer/base.py +25 -36
  31. tme/analyzer/peaks.py +39 -113
  32. tme/analyzer/proxy.py +1 -0
  33. tme/backends/_jax_utils.py +16 -15
  34. tme/backends/cupy_backend.py +9 -13
  35. tme/backends/jax_backend.py +19 -16
  36. tme/backends/npfftw_backend.py +27 -25
  37. tme/backends/pytorch_backend.py +4 -0
  38. tme/density.py +5 -4
  39. tme/filters/__init__.py +2 -2
  40. tme/filters/_utils.py +32 -7
  41. tme/filters/bandpass.py +225 -186
  42. tme/filters/ctf.py +117 -67
  43. tme/filters/reconstruction.py +38 -9
  44. tme/filters/wedge.py +88 -105
  45. tme/filters/whitening.py +1 -6
  46. tme/matching_data.py +24 -36
  47. tme/matching_exhaustive.py +14 -11
  48. tme/matching_scores.py +21 -12
  49. tme/matching_utils.py +13 -6
  50. tme/orientations.py +13 -3
  51. tme/parser.py +109 -29
  52. tme/preprocessor.py +2 -2
  53. pytme-0.3b0.dist-info/licenses/LICENSE +0 -153
  54. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/WHEEL +0 -0
  55. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/top_level.txt +0 -0
tme/filters/ctf.py CHANGED
@@ -7,7 +7,6 @@ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
7
7
  """
8
8
 
9
9
  import re
10
- import warnings
11
10
  from typing import Tuple, Dict
12
11
  from dataclasses import dataclass
13
12
 
@@ -16,13 +15,14 @@ import numpy as np
16
15
  from ..types import NDArray
17
16
  from ..backends import backend as be
18
17
  from .compose import ComposableFilter
19
- from ..parser import StarParser, XMLParser
18
+ from ..parser import StarParser, XMLParser, MDOCParser
20
19
  from ._utils import (
21
20
  frequency_grid_at_angle,
22
21
  compute_tilt_shape,
23
22
  crop_real_fourier,
24
23
  fftfreqn,
25
24
  shift_fourier,
25
+ pad_to_length,
26
26
  )
27
27
 
28
28
  __all__ = ["CTF", "CTFReconstructed", "create_ctf"]
@@ -34,39 +34,39 @@ class CTF(ComposableFilter):
34
34
  Generate a per-tilt contrast transfer function mask.
35
35
  """
36
36
 
37
- #: The shape of the to-be reconstructed volume.
37
+ #: The shape of the to-be created mask.
38
38
  shape: Tuple[int] = None
39
- #: The defocus value in x direction.
40
- defocus_x: float = None
39
+ #: The defocus value in x direction (in units of sampling rate).
40
+ defocus_x: Tuple[float] = None
41
41
  #: The tilt angles.
42
42
  angles: Tuple[float] = None
43
- #: The microscope projection axis, defaults to None.
43
+ #: The microscope projection axis, defaults to 2 (z).
44
44
  opening_axis: int = 2
45
- #: The axis along which the tilt is applied, defaults to 2 (z).
45
+ #: The axis along which the tilt is applied, defaults to 0 (x).
46
46
  tilt_axis: int = 0
47
- #: Whether to correct defocus gradient, defaults to 0 (x).
47
+ #: Whether to correct defocus gradient, defaults False.
48
48
  correct_defocus_gradient: bool = False
49
- #: The sampling rate, defaults to 1 Angstrom / Voxel.
49
+ #: The sampling rate, defaults to 1 Ångstrom / voxel.
50
50
  sampling_rate: Tuple[float] = 1
51
51
  #: The acceleration voltage in Volts, defaults to 300e3.
52
- acceleration_voltage: float = 300e3
53
- #: The spherical aberration coefficient, defaults to 2.7e7.
54
- spherical_aberration: float = 2.7e7
52
+ acceleration_voltage: Tuple[float] = 300e3
53
+ #: The spherical aberration, defaults to 2.7e7 (in units of sampling rate).
54
+ spherical_aberration: Tuple[float] = 2.7e7
55
55
  #: The amplitude contrast, defaults to 0.07.
56
- amplitude_contrast: float = 0.07
56
+ amplitude_contrast: Tuple[float] = 0.07
57
57
  #: The phase shift in degrees, defaults to 0.
58
- phase_shift: float = 0
58
+ phase_shift: Tuple[float] = 0
59
59
  #: The defocus angle in degrees, defaults to 0.
60
- defocus_angle: float = 0
61
- #: The defocus value in y direction, defaults to None.
62
- defocus_y: float = None
63
- #: Whether the returned CTF should be phase-flipped.
60
+ defocus_angle: Tuple[float] = 0
61
+ #: The defocus value in y direction, defaults to None (in units of sampling rate).
62
+ defocus_y: Tuple[float] = None
63
+ #: Whether the returned CTF should be phase-flipped, defaults to True.
64
64
  flip_phase: bool = True
65
- #: Whether to return a format compliant with rfft. Only relevant for single angles.
65
+ #: Whether to return a ctf mask for rfft (for :py:class:`CTFReconstructed`).
66
66
  return_real_fourier: bool = False
67
67
 
68
68
  @classmethod
69
- def from_file(cls, filename: str) -> "CTF":
69
+ def from_file(cls, filename: str, **kwargs) -> "CTF":
70
70
  """
71
71
  Initialize :py:class:`CTF` from file.
72
72
 
@@ -80,36 +80,50 @@ class CTF(ComposableFilter):
80
80
  +-------+---------------------------------------------------------+
81
81
  | .xml | WARP/M XML file |
82
82
  +-------+---------------------------------------------------------+
83
+ | .mdoc | SerialEM file |
84
+ +-------+---------------------------------------------------------+
83
85
  | .* | CTFFIND4 file |
84
86
  +-------+---------------------------------------------------------+
87
+ **kwargs : optional
88
+ Overwrite fields that cannot be extracted from input file.
85
89
  """
86
90
  func = _from_ctffind
87
91
  if filename.lower().endswith("star"):
88
- func = _from_gctf
92
+ func = _from_star
89
93
  elif filename.lower().endswith("xml"):
90
94
  func = _from_xml
95
+ elif filename.lower().endswith("mdoc"):
96
+ func = _from_mdoc
91
97
 
92
98
  data = func(filename=filename)
93
99
 
94
100
  # Pixel size needs to be overwritten by pixel size the ctf is generated for
95
- return cls(
96
- shape=None,
97
- angles=data.get("angles", None),
98
- defocus_x=data["defocus_1"],
99
- sampling_rate=data["pixel_size"],
100
- acceleration_voltage=data["acceleration_voltage"],
101
- spherical_aberration=data["spherical_aberration"],
102
- amplitude_contrast=data["amplitude_contrast"],
103
- phase_shift=data["additional_phase_shift"],
104
- defocus_angle=data["azimuth_astigmatism"],
105
- defocus_y=data["defocus_2"],
106
- )
101
+ init_kwargs = {
102
+ "shape": None,
103
+ "angles": data.get("angles", None),
104
+ "defocus_x": data["defocus_1"],
105
+ "sampling_rate": data["pixel_size"],
106
+ "acceleration_voltage": np.multiply(data["acceleration_voltage"], 1e3),
107
+ "spherical_aberration": data.get("spherical_aberration"),
108
+ "amplitude_contrast": data.get("amplitude_contrast"),
109
+ "phase_shift": data.get("additional_phase_shift"),
110
+ "defocus_angle": data.get("azimuth_astigmatism"),
111
+ "defocus_y": data["defocus_2"],
112
+ }
113
+ for k, v in kwargs.items():
114
+ if k in init_kwargs and init_kwargs.get(k) is None:
115
+ init_kwargs[k] = v
116
+ init_kwargs = {k: v for k, v in init_kwargs.items() if v is not None}
117
+ return cls(**init_kwargs)
107
118
 
108
119
  def __post_init__(self):
109
120
  self.defocus_angle = np.radians(self.defocus_angle)
110
121
  self.phase_shift = np.radians(self.phase_shift)
111
122
 
112
123
  def __call__(self, **kwargs) -> NDArray:
124
+ """
125
+ Returns a CTF stack of chosen parameters with DC component in the center.
126
+ """
113
127
  func_args = vars(self).copy()
114
128
  func_args.update(kwargs)
115
129
 
@@ -122,11 +136,6 @@ class CTF(ComposableFilter):
122
136
  "is_multiplicative_filter": True,
123
137
  }
124
138
 
125
- @staticmethod
126
- def _pad_to_length(arr, length: int):
127
- ret = np.atleast_1d(arr)
128
- return np.repeat(ret, length // ret.size)
129
-
130
139
  def weight(
131
140
  self,
132
141
  shape: Tuple[int],
@@ -134,7 +143,7 @@ class CTF(ComposableFilter):
134
143
  angles: Tuple[float],
135
144
  opening_axis: int = 2,
136
145
  tilt_axis: int = 0,
137
- amplitude_contrast: float = 0.07,
146
+ amplitude_contrast: Tuple[float] = 0.07,
138
147
  phase_shift: Tuple[float] = 0,
139
148
  defocus_angle: Tuple[float] = 0,
140
149
  defocus_y: Tuple[float] = None,
@@ -162,7 +171,7 @@ class CTF(ComposableFilter):
162
171
  The axis around which the wedge is opened, defaults to 2.
163
172
  tilt_axis : int, optional
164
173
  The axis along which the tilt is applied, defaults to 0.
165
- amplitude_contrast : float, optional
174
+ amplitude_contrast : tuple of float, optional
166
175
  The amplitude contrast, defaults to 0.07.
167
176
  phase_shift : tuple of float, optional
168
177
  The phase shift in radians, defaults to 0.
@@ -179,7 +188,7 @@ class CTF(ComposableFilter):
179
188
  spherical_aberration : float, optional
180
189
  The spherical aberration coefficient, defaults to 2.7e3.
181
190
  flip_phase : bool, optional
182
- Whether the returned CTF should be phase-flipped.
191
+ Whether the returned CTF should be phase-flipped, defaults to True.
183
192
  **kwargs : Dict
184
193
  Additional keyword arguments.
185
194
 
@@ -189,12 +198,13 @@ class CTF(ComposableFilter):
189
198
  A stack containing the CTF weight.
190
199
  """
191
200
  angles = np.atleast_1d(angles)
192
- defoci_x = self._pad_to_length(defocus_x, angles.size)
193
- defoci_y = self._pad_to_length(defocus_y, angles.size)
194
- phase_shift = self._pad_to_length(phase_shift, angles.size)
195
- defocus_angle = self._pad_to_length(defocus_angle, angles.size)
196
- spherical_aberration = self._pad_to_length(spherical_aberration, angles.size)
197
- amplitude_contrast = self._pad_to_length(amplitude_contrast, angles.size)
201
+ defoci_x = pad_to_length(defocus_x, angles.size)
202
+ defoci_y = pad_to_length(defocus_y, angles.size)
203
+ phase_shift = pad_to_length(phase_shift, angles.size)
204
+ defocus_angle = pad_to_length(defocus_angle, angles.size)
205
+ spherical_aberration = pad_to_length(spherical_aberration, angles.size)
206
+ amplitude_contrast = pad_to_length(amplitude_contrast, angles.size)
207
+ acceleration_voltage = pad_to_length(acceleration_voltage, angles.size)
198
208
 
199
209
  sampling_rate = np.max(sampling_rate)
200
210
  ctf_shape = compute_tilt_shape(
@@ -218,7 +228,7 @@ class CTF(ComposableFilter):
218
228
  defocus_x=defocus_x,
219
229
  defocus_y=defocus_y,
220
230
  sampling_rate=sampling_rate,
221
- acceleration_voltage=self.acceleration_voltage,
231
+ acceleration_voltage=acceleration_voltage[index],
222
232
  correct_defocus_gradient=correction,
223
233
  spherical_aberration=spherical_aberration[index],
224
234
  cutoff_frequency=cutoff_frequency,
@@ -325,7 +335,7 @@ class CTFReconstructed(CTF):
325
335
  return stack
326
336
 
327
337
 
328
- def _from_xml(filename: str):
338
+ def _from_xml(filename: str) -> Dict:
329
339
  data = XMLParser(filename)
330
340
 
331
341
  params = {
@@ -353,6 +363,7 @@ def _from_xml(filename: str):
353
363
  params["PhaseShift"] = [
354
364
  ctf_phase[i]["@attributes"]["Value"] for i in range(len(ctf_phase))
355
365
  ]
366
+ params["PhaseShift"] = np.degrees(params["PhaseShift"])
356
367
  ctf_ast = data["GridCTFDefocusAngle"]["Node"]
357
368
  params["DefocusAngle"] = [
358
369
  ctf_ast[i]["@attributes"]["Value"] for i in range(len(ctf_ast))
@@ -384,7 +395,7 @@ def _from_xml(filename: str):
384
395
  return {k: params[v] for k, v in mapping.items()}
385
396
 
386
397
 
387
- def _from_ctffind(filename: str):
398
+ def _from_ctffind(filename: str) -> Dict:
388
399
  parameter_regex = {
389
400
  "pixel_size": r"Pixel size: ([0-9.]+) Angstroms",
390
401
  "acceleration_voltage": r"acceleration voltage: ([0-9.]+) keV",
@@ -428,15 +439,58 @@ def _from_ctffind(filename: str):
428
439
  return output
429
440
 
430
441
 
431
- def _from_gctf(filename: str):
442
+ def _from_star(filename: str) -> Dict:
432
443
  parser = StarParser(filename)
433
- ctf_data = parser["data_"]
444
+
445
+ if "data_stopgap_wedgelist" in parser:
446
+ key = "data_stopgap_wedgelist"
447
+ mapping = {
448
+ "angles": ("_tilt_angle", float, 1),
449
+ "defocus_1": ("_defocus", float, 1e4),
450
+ "defocus_2": (None, float, 1e4),
451
+ "pixel_size": ("_pixelsize", float, 1),
452
+ "acceleration_voltage": ("_voltage", float, 1),
453
+ "spherical_aberration": ("_cs", float, 1e7),
454
+ "amplitude_contrast": ("_amp_contrast", float, 1),
455
+ "additional_phase_shift": (None, float, 1),
456
+ "azimuth_astigmatism": (None, float, 1),
457
+ }
458
+ else:
459
+ key = "data_"
460
+ mapping = {
461
+ "defocus_1": ("_rlnDefocusU", float, 1),
462
+ "defocus_2": ("_rlnDefocusV", float, 1),
463
+ "pixel_size": ("_rlnDetectorPixelSize", float, 1),
464
+ "acceleration_voltage": ("_rlnVoltage", float, 1),
465
+ "spherical_aberration": ("_rlnSphericalAberration", float, 1),
466
+ "amplitude_contrast": ("_rlnAmplitudeContrast", float, 1),
467
+ "additional_phase_shift": (None, float, 1),
468
+ "azimuth_astigmatism": ("_rlnDefocusAngle", float, 1),
469
+ }
470
+
471
+ output = {}
472
+ ctf_data = parser[key]
473
+ for out_key, (key, key_dtype, scale) in mapping.items():
474
+ key_value = ctf_data.get(key)
475
+ if key_value is not None:
476
+ try:
477
+ key_value = [key_dtype(x) * scale for x in key_value]
478
+ except Exception:
479
+ pass
480
+ output[out_key] = key_value
481
+ return output
482
+
483
+
484
+ def _from_mdoc(filename: str) -> Dict:
485
+ parser = MDOCParser(filename)
434
486
 
435
487
  mapping = {
436
- "defocus_1": ("_rlnDefocusU", float),
437
- "defocus_2": ("_rlnDefocusV", float),
488
+ "angles": ("TiltAngle", float),
489
+ "defocus_1": ("Defocus", float),
490
+ "acceleration_voltage": ("Voltage", float),
491
+ # These will be None, but on purpose
438
492
  "pixel_size": ("_rlnDetectorPixelSize", float),
439
- "acceleration_voltage": ("_rlnVoltage", float),
493
+ "defocus_2": ("Defocus2", float),
440
494
  "spherical_aberration": ("_rlnSphericalAberration", float),
441
495
  "amplitude_contrast": ("_rlnAmplitudeContrast", float),
442
496
  "additional_phase_shift": (None, float),
@@ -444,14 +498,10 @@ def _from_gctf(filename: str):
444
498
  }
445
499
  output = {}
446
500
  for out_key, (key, key_dtype) in mapping.items():
447
- if key not in ctf_data and key is not None:
448
- warnings.warn(f"ctf_data is missing key {key}.")
449
-
450
- key_value = ctf_data.get(key, [0])
451
- output[out_key] = [key_dtype(x) for x in key_value]
501
+ output[out_key] = parser.get(key, None)
452
502
 
453
- longest_key = max(map(len, output.values()))
454
- output = {k: v * longest_key if len(v) == 1 else v for k, v in output.items()}
503
+ # Adjust convention and convert to Angstrom
504
+ output["defocus_1"] = np.multiply(output["defocus_1"], -1e4)
455
505
  return output
456
506
 
457
507
 
@@ -589,10 +639,10 @@ def create_ctf(
589
639
  frequency_mask = frequency_grid < cutoff_frequency
590
640
 
591
641
  # k^2*π*λ(dx - 0.5 * sph_abb * λ^2 * k^2) + phase_shift + ampl_contrast_term)
592
- np.square(frequency_grid, out=frequency_grid)
642
+ frequency_grid = np.square(frequency_grid, out=frequency_grid)
593
643
  chi = defocus_x - 0.5 * aberration * frequency_grid
594
- np.multiply(chi, np.pi * electron_wavelength, out=chi)
595
- np.multiply(chi, frequency_grid, out=chi)
644
+ chi = np.multiply(chi, np.pi * electron_wavelength, out=chi)
645
+ chi = np.multiply(chi, frequency_grid, out=chi)
596
646
  chi += phase_shift
597
647
  chi += np.arctan(
598
648
  np.divide(
@@ -600,6 +650,6 @@ def create_ctf(
600
650
  np.sqrt(1 - np.square(amplitude_contrast)),
601
651
  )
602
652
  )
603
- np.sin(-chi, out=chi)
604
- np.multiply(chi, frequency_mask, out=chi)
653
+ chi = np.sin(-chi, out=chi)
654
+ chi = np.multiply(chi, frequency_mask, out=chi)
605
655
  return chi
@@ -11,14 +11,14 @@ from dataclasses import dataclass
11
11
 
12
12
  import numpy as np
13
13
 
14
- from ..types import NDArray
15
14
  from ..backends import backend as be
15
+ from ..types import NDArray, BackendArray
16
16
 
17
17
  from .compose import ComposableFilter
18
18
  from ..rotations import euler_to_rotationmatrix
19
19
  from ._utils import crop_real_fourier, shift_fourier, create_reconstruction_filter
20
20
 
21
- __all__ = ["ReconstructFromTilt"]
21
+ __all__ = ["ReconstructFromTilt", "ShiftFourier"]
22
22
 
23
23
 
24
24
  @dataclass
@@ -52,7 +52,9 @@ class ReconstructFromTilt(ComposableFilter):
52
52
  shape : tuple of int
53
53
  The shape of the reconstruction volume.
54
54
  data : BackendArray
55
- D-dimensional image stack with shape (n, ...)
55
+ D-dimensional image stack with shape (n, ...). The data is assumed to be
56
+ a Fourier transform of the stack you are trying to reconstruct with
57
+ DC component in the center.
56
58
  angles : tuple of float
57
59
  Angle of each individual tilt.
58
60
  return_real_fourier : bool, optional
@@ -87,13 +89,14 @@ class ReconstructFromTilt(ComposableFilter):
87
89
 
88
90
  ret = self.reconstruct(**func_args)
89
91
 
92
+ ret = shift_fourier(data=ret, shape_is_real_fourier=False)
90
93
  if return_real_fourier:
91
94
  ret = crop_real_fourier(ret)
92
95
 
93
96
  return {
94
97
  "data": ret,
95
98
  "shape": func_args["shape"],
96
- "shape_is_real_fourier": return_real_fourier,
99
+ "return_real_fourier": return_real_fourier,
97
100
  "is_multiplicative_filter": False,
98
101
  }
99
102
 
@@ -114,7 +117,7 @@ class ReconstructFromTilt(ComposableFilter):
114
117
  Parameters
115
118
  ----------
116
119
  data : NDArray
117
- The tilt series data.
120
+ The Fourier transform of tilt series data.
118
121
  shape : tuple of int
119
122
  Shape of the reconstruction.
120
123
  angles : tuple of float
@@ -138,9 +141,9 @@ class ReconstructFromTilt(ComposableFilter):
138
141
  return data
139
142
 
140
143
  data = be.to_backend_array(data)
141
- volume_temp = be.zeros(shape, dtype=be._float_dtype)
142
- volume_temp_rotated = be.zeros(shape, dtype=be._float_dtype)
143
- volume = be.zeros(shape, dtype=be._float_dtype)
144
+ volume_temp = be.zeros(shape, dtype=data.dtype)
145
+ volume_temp_rotated = be.zeros(shape, dtype=data.dtype)
146
+ volume = be.zeros(shape, dtype=data.dtype)
144
147
 
145
148
  slices = tuple(slice(a // 2, (a // 2) + 1) for a in shape)
146
149
  subset = tuple(
@@ -187,4 +190,30 @@ class ReconstructFromTilt(ComposableFilter):
187
190
  )
188
191
  volume = be.add(volume, volume_temp_rotated, out=volume)
189
192
 
190
- return shift_fourier(data=volume, shape_is_real_fourier=False)
193
+ return volume
194
+
195
+
196
+ class ShiftFourier(ComposableFilter):
197
+ def __call__(
198
+ self,
199
+ data: BackendArray,
200
+ shape_is_real_fourier: bool = False,
201
+ return_real_fourier: bool = True,
202
+ **kwargs,
203
+ ):
204
+ ret = []
205
+ for index in range(data.shape[0]):
206
+ mask = be.to_numpy_array(data[index])
207
+
208
+ mask = shift_fourier(data=mask, shape_is_real_fourier=shape_is_real_fourier)
209
+ if return_real_fourier:
210
+ mask = crop_real_fourier(mask)
211
+ ret.append(mask[None])
212
+ ret = np.concatenate(ret, axis=0)
213
+
214
+ return {
215
+ "data": ret,
216
+ "shape": kwargs.get("shape"),
217
+ "return_real_fourier": return_real_fourier,
218
+ "is_multiplicative_filter": False,
219
+ }