pyNFFT3 0.2.1__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.
Files changed (47) hide show
  1. pyNFFT3/NFCT.py +340 -0
  2. pyNFFT3/NFFT.py +326 -0
  3. pyNFFT3/NFMT.py +1 -0
  4. pyNFFT3/NFST.py +335 -0
  5. pyNFFT3/__init__.py +165 -0
  6. pyNFFT3/fastsum.py +325 -0
  7. pyNFFT3/flags.py +231 -0
  8. pyNFFT3/lib/AVX/libfastsumjulia.dll +0 -0
  9. pyNFFT3/lib/AVX/libfastsumjulia.dylib +0 -0
  10. pyNFFT3/lib/AVX/libfastsumjulia.so +0 -0
  11. pyNFFT3/lib/AVX/libnfctjulia.dll +0 -0
  12. pyNFFT3/lib/AVX/libnfctjulia.dylib +0 -0
  13. pyNFFT3/lib/AVX/libnfctjulia.so +0 -0
  14. pyNFFT3/lib/AVX/libnfftjulia.dll +0 -0
  15. pyNFFT3/lib/AVX/libnfftjulia.dylib +0 -0
  16. pyNFFT3/lib/AVX/libnfftjulia.so +0 -0
  17. pyNFFT3/lib/AVX/libnfstjulia.dll +0 -0
  18. pyNFFT3/lib/AVX/libnfstjulia.dylib +0 -0
  19. pyNFFT3/lib/AVX/libnfstjulia.so +0 -0
  20. pyNFFT3/lib/AVX2/libfastsumjulia.dll +0 -0
  21. pyNFFT3/lib/AVX2/libfastsumjulia.dylib +0 -0
  22. pyNFFT3/lib/AVX2/libfastsumjulia.so +0 -0
  23. pyNFFT3/lib/AVX2/libnfctjulia.dll +0 -0
  24. pyNFFT3/lib/AVX2/libnfctjulia.dylib +0 -0
  25. pyNFFT3/lib/AVX2/libnfctjulia.so +0 -0
  26. pyNFFT3/lib/AVX2/libnfftjulia.dll +0 -0
  27. pyNFFT3/lib/AVX2/libnfftjulia.dylib +0 -0
  28. pyNFFT3/lib/AVX2/libnfftjulia.so +0 -0
  29. pyNFFT3/lib/AVX2/libnfstjulia.dll +0 -0
  30. pyNFFT3/lib/AVX2/libnfstjulia.dylib +0 -0
  31. pyNFFT3/lib/AVX2/libnfstjulia.so +0 -0
  32. pyNFFT3/lib/SSE2/libfastsumjulia.dll +0 -0
  33. pyNFFT3/lib/SSE2/libfastsumjulia.dylib +0 -0
  34. pyNFFT3/lib/SSE2/libfastsumjulia.so +0 -0
  35. pyNFFT3/lib/SSE2/libnfctjulia.dll +0 -0
  36. pyNFFT3/lib/SSE2/libnfctjulia.dylib +0 -0
  37. pyNFFT3/lib/SSE2/libnfctjulia.so +0 -0
  38. pyNFFT3/lib/SSE2/libnfftjulia.dll +0 -0
  39. pyNFFT3/lib/SSE2/libnfftjulia.dylib +0 -0
  40. pyNFFT3/lib/SSE2/libnfftjulia.so +0 -0
  41. pyNFFT3/lib/SSE2/libnfstjulia.dll +0 -0
  42. pyNFFT3/lib/SSE2/libnfstjulia.dylib +0 -0
  43. pyNFFT3/lib/SSE2/libnfstjulia.so +0 -0
  44. pynfft3-0.2.1.dist-info/METADATA +40 -0
  45. pynfft3-0.2.1.dist-info/RECORD +47 -0
  46. pynfft3-0.2.1.dist-info/WHEEL +4 -0
  47. pynfft3-0.2.1.dist-info/licenses/LICENSE +674 -0
pyNFFT3/NFCT.py ADDED
@@ -0,0 +1,340 @@
1
+ import ctypes
2
+ import numpy as np
3
+ from .flags import *
4
+ from . import _nfctlib
5
+ from . import nfct_plan
6
+
7
+ # Set arugment and return types for functions
8
+ _nfctlib.jnfct_init.argtypes = [
9
+ ctypes.POINTER(nfct_plan),
10
+ ctypes.c_int32,
11
+ ctypes.POINTER(ctypes.c_int32),
12
+ ctypes.c_int32,
13
+ ctypes.POINTER(ctypes.c_int32),
14
+ ctypes.c_int32,
15
+ ctypes.c_uint32,
16
+ ctypes.c_uint32,
17
+ ]
18
+
19
+ _nfctlib.jnfct_alloc.restype = ctypes.POINTER(nfct_plan)
20
+ _nfctlib.jnfct_finalize.argtypes = [ctypes.POINTER(nfct_plan)]
21
+
22
+ _nfctlib.jnfct_set_x.argtypes = [
23
+ ctypes.POINTER(nfct_plan),
24
+ np.ctypeslib.ndpointer(np.float64, flags="C"),
25
+ ]
26
+ _nfctlib.jnfct_set_f.argtypes = [
27
+ ctypes.POINTER(nfct_plan),
28
+ np.ctypeslib.ndpointer(np.float64, ndim=1, flags="C"),
29
+ ]
30
+ _nfctlib.jnfct_set_fhat.argtypes = [
31
+ ctypes.POINTER(nfct_plan),
32
+ np.ctypeslib.ndpointer(np.float64, ndim=1, flags="C"),
33
+ ]
34
+
35
+ _nfctlib.jnfct_trafo.argtypes = [ctypes.POINTER(nfct_plan)]
36
+ _nfctlib.jnfct_adjoint.argtypes = [ctypes.POINTER(nfct_plan)]
37
+ _nfctlib.jnfct_trafo_direct.argtypes = [ctypes.POINTER(nfct_plan)]
38
+ _nfctlib.jnfct_adjoint_direct.argtypes = [ctypes.POINTER(nfct_plan)]
39
+
40
+
41
+ class NFCT:
42
+ def __init__(self, N, M, n=None, m=default_window_cut_off, f1=None, f2=f2_default):
43
+ """
44
+ Class to perform non-equispaced fast cosine transforms (NFCT)
45
+ with a dimension of **D**.
46
+ Just **N** and **M** are required for initializing a plan.
47
+ """
48
+ self.plan = _nfctlib.jnfct_alloc()
49
+ self.N = N # bandwidth tuple
50
+ N_ct = N.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))
51
+ self.M = M # number of nodes
52
+ self.n = n # oversampling per dimension
53
+ self.m = m # window size
54
+ self.D = len(N) # dimensions
55
+
56
+ if any(x <= 0 for x in N):
57
+ raise ValueError(f"Invalid N: {N}. Argument must be a positive integer")
58
+
59
+ if sum(x % 2 for x in N) != 0:
60
+ raise ValueError(f"Invalid N: {N}. Argument must be an even integer")
61
+
62
+ if M <= 0:
63
+ raise ValueError(f"Invalid M: {M}. Argument must be a positive integer")
64
+
65
+ if n is None:
66
+ self.n = (2 ** (np.ceil(np.log(self.N) / np.log(2)) + 1)).astype("int32")
67
+ n_ct = self.n.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))
68
+
69
+ if any(x <= 0 for x in self.n):
70
+ raise ValueError(
71
+ f"Invalid n: {self.n}. Argument must be a positive integer"
72
+ )
73
+
74
+ if any(x <= y for x, y in zip(self.n, N)):
75
+ raise ValueError(f"Invalid n: {self.n}. Argument must fulfil n_i > N_i")
76
+
77
+ if sum(x % 2 for x in self.n) != 0:
78
+ raise ValueError(f"Invalid n: {self.n}. Argument must be an even integer")
79
+
80
+ if m <= 0:
81
+ raise ValueError(f"Invalid m: {m}. Argument must be a positive integer")
82
+
83
+ if f1 is None:
84
+ self.f1 = f1_default if self.D > 1 else f1_default_1d
85
+ else:
86
+ self.f1 = f1
87
+
88
+ self.f2 = f2 # FFTW flags
89
+ _nfctlib.jnfct_init(
90
+ self.plan, self.D, N_ct, self.M, n_ct, self.m, self.f1, self.f2
91
+ )
92
+ self.init_done = True # bool for plan init
93
+ self.finalized = False # bool for finalizer
94
+ self.x = None # nodes, will be set later
95
+ self.f = None # function values
96
+ self.fhat = None # Fourier coefficients
97
+
98
+ def __del__(self):
99
+ self.finalize_plan()
100
+
101
+ def nfct_finalize_plan(self):
102
+ """
103
+ Finalizes an NFCT plan.
104
+ This function does not have to be called by the user.
105
+ """
106
+ _nfctlib.jnfct_finalize.argtypes = (ctypes.POINTER(nfct_plan),) # P
107
+
108
+ if not self.init_done:
109
+ raise ValueError("NFST not initialized.")
110
+
111
+ if not self.finalized:
112
+ self.finalized = True
113
+ _nfctlib.jnfct_finalize(self.plan)
114
+
115
+ def finalize_plan(self):
116
+ """
117
+ Alternative call for **nfct_finalize_plan()**
118
+ """
119
+ return self.nfct_finalize_plan()
120
+
121
+ def nfct_init(self):
122
+ """
123
+ Initializes the NFCT plan in C.
124
+ This function does not have to be called by the user.
125
+ """
126
+ # Convert N and n to numpy arrays for passing them to C
127
+ Nv = np.array(self.N, dtype=np.int32)
128
+ n = np.array(self.n, dtype=np.int32)
129
+
130
+ # Call init for memory allocation
131
+ ptr = _nfctlib.jnfct_alloc()
132
+
133
+ # Set the pointer
134
+ self.plan = ctypes.cast(ptr, ctypes.POINTER(nfct_plan))
135
+
136
+ # Initialize values
137
+ _nfctlib.jnfct_init(
138
+ self.plan,
139
+ ctypes.c_int(self.D),
140
+ ctypes.cast(Nv.ctypes.data, ctypes.POINTER(ctypes.c_int)),
141
+ ctypes.c_int(self.M),
142
+ ctypes.cast(n.ctypes.data, ctypes.POINTER(ctypes.c_int)),
143
+ ctypes.c_int(self.m),
144
+ ctypes.c_uint(self.f1),
145
+ ctypes.c_uint(self.f2),
146
+ )
147
+ self.init_done = True
148
+
149
+ def init(self):
150
+ """
151
+ Alternative call for **nfft_init()**
152
+ """
153
+ return self.nfct_init()
154
+
155
+ @property
156
+ def x(self):
157
+ return self._X
158
+
159
+ @x.setter
160
+ def x(self, value):
161
+ if value is not None:
162
+ if not (
163
+ isinstance(value, np.ndarray)
164
+ and value.dtype == np.float64
165
+ and value.flags["C"]
166
+ ):
167
+ raise RuntimeError("x has to be C-continuous, numpy float64 array")
168
+ if self.D == 1:
169
+ _nfctlib.jnfct_set_x.restype = np.ctypeslib.ndpointer(
170
+ dtype=np.float64, ndim=2, shape=self.M, flags="C"
171
+ )
172
+ else:
173
+ _nfctlib.jnfct_set_x.restype = np.ctypeslib.ndpointer(
174
+ dtype=np.float64, ndim=2, shape=(self.M, self.D), flags="C"
175
+ )
176
+ self._X = _nfctlib.jnfct_set_x(self.plan, value)
177
+
178
+ @property
179
+ def f(self):
180
+ return self._f
181
+
182
+ @f.setter
183
+ def f(self, value):
184
+ if value is not None:
185
+ if not (
186
+ isinstance(value, np.ndarray)
187
+ and value.dtype == np.float64
188
+ and value.flags["C"]
189
+ ):
190
+ raise RuntimeError("f has to be C-continuous, numpy float64 array")
191
+ _nfctlib.jnfct_set_f.restype = np.ctypeslib.ndpointer(
192
+ np.float64, ndim=1, shape=self.M, flags="C"
193
+ )
194
+ self._f = _nfctlib.jnfct_set_f(self.plan, value)
195
+
196
+ @property
197
+ def fhat(self):
198
+ return self._fhat
199
+
200
+ @fhat.setter
201
+ def fhat(self, value):
202
+ Ns = np.prod(self.N)
203
+ if value is not None:
204
+ if not (isinstance(value, np.ndarray) and value.dtype == np.float64):
205
+ raise RuntimeError("fhat has to be a numpy float64 array")
206
+ if not value.flags["C"]:
207
+ raise RuntimeError("fhat has to be C-continuous")
208
+ if value.size != Ns:
209
+ raise ValueError(f"fhat has to be an array of size {Ns}")
210
+ _nfctlib.jnfct_set_fhat.argtypes = [
211
+ ctypes.POINTER(nfct_plan),
212
+ np.ctypeslib.ndpointer(np.float64, ndim=1, flags="C"),
213
+ ]
214
+ _nfctlib.jnfct_set_fhat.restype = np.ctypeslib.ndpointer(
215
+ np.float64, ndim=1, shape=Ns, flags="C_CONTIGUOUS"
216
+ )
217
+ self._fhat = _nfctlib.jnfct_set_fhat(self.plan, value)
218
+
219
+ @property
220
+ def num_threads(self):
221
+ return _nfctlib.nfft_get_num_threads()
222
+
223
+ def nfct_trafo(self):
224
+ """
225
+ Computes the NDCT via the fast NFCT algorithm for the provided nodes in **x** and coefficients in **fhat**.
226
+ """
227
+ Ns = np.prod(self.N)
228
+ _nfctlib.jnfct_trafo.restype = np.ctypeslib.ndpointer(
229
+ np.float64, shape=Ns, flags="C"
230
+ )
231
+ # Prevent bad stuff from happening
232
+ if self.finalized:
233
+ raise RuntimeError("NFCT already finalized")
234
+
235
+ if not hasattr(self, "fhat"):
236
+ raise ValueError("fhat has not been set.")
237
+
238
+ if not hasattr(self, "x"):
239
+ raise ValueError("x has not been set.")
240
+
241
+ ptr = _nfctlib.jnfct_trafo(self.plan)
242
+ self.f = ptr
243
+
244
+ def trafo(self):
245
+ """
246
+ Alternative call for **nfct_trafo()**
247
+ """
248
+ return self.nfct_trafo()
249
+
250
+ def nfct_trafo_direct(self):
251
+ """
252
+ Computes the NDCT via naive matrix-vector multiplication for the provided nodes in **x** and coefficients in **fhat**.
253
+ """
254
+ _nfctlib.jnfct_trafo_direct.restype = np.ctypeslib.ndpointer(
255
+ np.float64, shape=self.M, flags="C"
256
+ )
257
+ # Prevent bad stuff from happening
258
+ if self.finalized:
259
+ raise RuntimeError("NFCT already finalized")
260
+
261
+ if self.fhat is None:
262
+ raise ValueError("fhat has not been set.")
263
+
264
+ if self.x is None:
265
+ raise ValueError("x has not been set.")
266
+
267
+ ptr = _nfctlib.jnfct_trafo_direct(self.plan)
268
+ self.f = ptr
269
+
270
+ def trafo_direct(self):
271
+ """
272
+ Alternative call for **nfct_trafo_direct()**
273
+ """
274
+ return self.nfct_trafo_direct()
275
+
276
+ def nfct_transposed(self):
277
+ """
278
+ Computes the transposed NDCT via the fast transposed NFCT algorithm for the provided nodes in **x** and coefficients in **f**.
279
+ """
280
+ Ns = np.prod(self.N)
281
+ _nfctlib.jnfct_adjoint.restype = np.ctypeslib.ndpointer(
282
+ np.float64, shape=Ns, flags="C"
283
+ )
284
+ # Prevent bad stuff from happening
285
+ if self.finalized:
286
+ raise RuntimeError("NFCT already finalized")
287
+
288
+ if self.f is None:
289
+ raise ValueError("f has not been set.")
290
+
291
+ if self.x is None:
292
+ raise ValueError("x has not been set.")
293
+
294
+ ptr = _nfctlib.jnfct_adjoint(self.plan)
295
+ self.fhat = ptr
296
+
297
+ def nfct_transposed_direct(self):
298
+ """
299
+ Computes the transposed NDCT via naive matrix-vector multiplication for provided nodes for the provided nodes in **x** and coefficients in **f**.
300
+ """
301
+ Ns = np.prod(self.N)
302
+ _nfctlib.jnfct_adjoint_direct.restype = np.ctypeslib.ndpointer(
303
+ np.float64, shape=Ns, flags="C"
304
+ )
305
+ # Prevent bad stuff from happening
306
+ if self.finalized:
307
+ raise RuntimeError("NFCT already finalized")
308
+
309
+ if self.f is None:
310
+ raise ValueError("f has not been set.")
311
+
312
+ if self.x is None:
313
+ raise ValueError("x has not been set.")
314
+
315
+ ptr = _nfctlib.jnfct_adjoint_direct(self.plan)
316
+ self.fhat = ptr
317
+
318
+ def nfct_adjoint(self):
319
+ """
320
+ Alternative call for **nfct_transposed()**
321
+ """
322
+ return self.nfct_transposed()
323
+
324
+ def nfct_adjoint_direct(self):
325
+ """
326
+ Alternative call for **nfct_transposed_direct()**
327
+ """
328
+ return self.nfct_transposed_direct()
329
+
330
+ def adjoint(self):
331
+ """
332
+ Alternative call for **nfct_adjoint()**
333
+ """
334
+ return self.nfct_adjoint()
335
+
336
+ def adjoint_direct(self):
337
+ """
338
+ Alternative call for **nfct_adjoint_direct()**
339
+ """
340
+ return self.nfct_adjoint_direct()
pyNFFT3/NFFT.py ADDED
@@ -0,0 +1,326 @@
1
+ import ctypes
2
+ import numpy as np
3
+ from .flags import *
4
+ from . import _nfftlib
5
+ from . import nfft_plan
6
+
7
+ # Set arugment and return types for functions
8
+ _nfftlib.jnfft_init.argtypes = [
9
+ ctypes.POINTER(nfft_plan),
10
+ ctypes.c_int32,
11
+ ctypes.POINTER(ctypes.c_int32),
12
+ ctypes.c_int32,
13
+ ctypes.POINTER(ctypes.c_int32),
14
+ ctypes.c_int32,
15
+ ctypes.c_uint32,
16
+ ctypes.c_uint32,
17
+ ]
18
+
19
+ _nfftlib.jnfft_alloc.restype = ctypes.POINTER(nfft_plan)
20
+ _nfftlib.jnfft_finalize.argtypes = [ctypes.POINTER(nfft_plan)]
21
+
22
+ _nfftlib.jnfft_set_x.argtypes = [
23
+ ctypes.POINTER(nfft_plan),
24
+ np.ctypeslib.ndpointer(np.float64, flags="C"),
25
+ ]
26
+ _nfftlib.jnfft_set_f.argtypes = [
27
+ ctypes.POINTER(nfft_plan),
28
+ np.ctypeslib.ndpointer(np.complex128, ndim=1, flags="C"),
29
+ ]
30
+ _nfftlib.jnfft_set_fhat.argtypes = [
31
+ ctypes.POINTER(nfft_plan),
32
+ np.ctypeslib.ndpointer(np.complex128, ndim=1, flags="C"),
33
+ ]
34
+
35
+ _nfftlib.jnfft_trafo.argtypes = [ctypes.POINTER(nfft_plan)]
36
+ _nfftlib.jnfft_adjoint.argtypes = [ctypes.POINTER(nfft_plan)]
37
+ _nfftlib.jnfft_trafo_direct.argtypes = [ctypes.POINTER(nfft_plan)]
38
+ _nfftlib.jnfft_adjoint_direct.argtypes = [ctypes.POINTER(nfft_plan)]
39
+
40
+
41
+ class NFFT:
42
+ """
43
+ Class to perform non-equispaced fast Fourier transforms (NFFT)
44
+ considering a **D**-dimensional trigonometric polynomial.
45
+ Just **N** and **M** are required for initializing a plan.
46
+ """
47
+
48
+ def __init__(self, N, M, n=None, m=default_window_cut_off, f1=None, f2=f2_default):
49
+ self.plan = _nfftlib.jnfft_alloc()
50
+ self.N = N # bandwidth tuple
51
+ N_ct = N.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))
52
+ self.M = M # number of nodes
53
+ self.n = n # oversampling per dimension
54
+ self.m = m # window size
55
+ self.D = len(N) # dimensions
56
+
57
+ if any(x <= 0 for x in N):
58
+ raise ValueError(f"Invalid N: {N}. Argument must be a positive integer")
59
+
60
+ if sum(x % 2 for x in N) != 0:
61
+ raise ValueError(f"Invalid N: {N}. Argument must be an even integer")
62
+
63
+ if M <= 0:
64
+ raise ValueError(f"Invalid M: {M}. Argument must be a positive integer")
65
+
66
+ if n is None:
67
+ self.n = (2 ** (np.ceil(np.log(self.N) / np.log(2)) + 1)).astype("int32")
68
+ n_ct = self.n.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))
69
+
70
+ if any(x <= 0 for x in self.n):
71
+ raise ValueError(
72
+ f"Invalid n: {self.n}. Argument must be a positive integer"
73
+ )
74
+
75
+ if any(x <= y for x, y in zip(self.n, N)):
76
+ raise ValueError(f"Invalid n: {self.n}. Argument must fulfil n_i > N_i")
77
+
78
+ if sum(x % 2 for x in self.n) != 0:
79
+ raise ValueError(f"Invalid n: {self.n}. Argument must be an even integer")
80
+
81
+ if m <= 0:
82
+ raise ValueError(f"Invalid m: {m}. Argument must be a positive integer")
83
+
84
+ if f1 is None:
85
+ self.f1 = f1_default if self.D > 1 else f1_default_1d
86
+ else:
87
+ self.f1 = f1
88
+
89
+ self.f2 = f2 # FFTW flags
90
+ _nfftlib.jnfft_init(
91
+ self.plan, self.D, N_ct, self.M, n_ct, self.m, self.f1, self.f2
92
+ )
93
+ self.init_done = True # bool for plan init
94
+ self.finalized = False # bool for finalizer
95
+ self.x = None # nodes, will be set later
96
+ self.f = None # function values
97
+ self.fhat = None # Fourier coefficients
98
+
99
+ def __del__(self):
100
+ self.finalize_plan()
101
+
102
+ def nfft_finalize_plan(self):
103
+ """
104
+ Finalizes an NFFT plan.
105
+ This function does not have to be called by the user.
106
+ """
107
+ _nfftlib.jnfft_finalize.argtypes = (ctypes.POINTER(nfft_plan),) # P
108
+
109
+ if not self.init_done:
110
+ raise ValueError("NFFT not initialized.")
111
+
112
+ if not self.finalized:
113
+ self.finalized = True
114
+ _nfftlib.jnfft_finalize(self.plan)
115
+
116
+ def finalize_plan(self):
117
+ """
118
+ Alternate call for **nfft_finalize_plan()**
119
+ """
120
+ return self.nfft_finalize_plan()
121
+
122
+ def nfft_init(self):
123
+ """
124
+ Initializes the NFFT plan in C.
125
+ This function does not have to be called by the user.
126
+ """
127
+ # Convert N and n to numpy arrays for passing them to C
128
+ Nv = np.array(self.N, dtype=np.int32)
129
+ n = np.array(self.n, dtype=np.int32)
130
+
131
+ # Call init for memory allocation
132
+ ptr = _nfftlib.jnfft_alloc()
133
+
134
+ # Set the pointer
135
+ self.plan = ctypes.cast(ptr, ctypes.POINTER(nfft_plan))
136
+
137
+ # Initialize values
138
+ _nfftlib.jnfft_init(
139
+ self.plan,
140
+ ctypes.c_int(self.D),
141
+ ctypes.cast(Nv.ctypes.data, ctypes.POINTER(ctypes.c_int)),
142
+ ctypes.c_int(self.M),
143
+ ctypes.cast(n.ctypes.data, ctypes.POINTER(ctypes.c_int)),
144
+ ctypes.c_int(self.m),
145
+ ctypes.c_uint(self.f1),
146
+ ctypes.c_uint(self.f2),
147
+ )
148
+ self.init_done = True
149
+
150
+ def init(self):
151
+ """
152
+ Alternate call for **nfft_init()**
153
+ """
154
+ return self.nfft_init()
155
+
156
+ @property
157
+ def x(self):
158
+ return self._X
159
+
160
+ @x.setter
161
+ def x(self, value):
162
+ if value is not None:
163
+ if not (
164
+ isinstance(value, np.ndarray)
165
+ and value.dtype == np.float64
166
+ and value.flags["C"]
167
+ ):
168
+ raise RuntimeError("x has to be C-continuous, numpy float64 array")
169
+ if self.D == 1:
170
+ _nfftlib.jnfft_set_x.restype = np.ctypeslib.ndpointer(
171
+ dtype=np.float64, ndim=2, shape=self.M, flags="C"
172
+ )
173
+ else:
174
+ _nfftlib.jnfft_set_x.restype = np.ctypeslib.ndpointer(
175
+ dtype=np.float64, ndim=2, shape=(self.M, self.D), flags="C"
176
+ )
177
+ self._X = _nfftlib.jnfft_set_x(self.plan, value)
178
+
179
+ @property
180
+ def f(self):
181
+ return self._f
182
+
183
+ @f.setter
184
+ def f(self, value):
185
+ if value is not None:
186
+ if not (
187
+ isinstance(value, np.ndarray)
188
+ and value.dtype == np.complex128
189
+ and value.flags["C"]
190
+ ):
191
+ raise RuntimeError("f has to be C-continuous, numpy complex128 array")
192
+ _nfftlib.jnfft_set_f.restype = np.ctypeslib.ndpointer(
193
+ np.complex128, ndim=1, shape=self.M, flags="C"
194
+ )
195
+ self._f = _nfftlib.jnfft_set_f(self.plan, value)
196
+
197
+ @property
198
+ def fhat(self):
199
+ return self._fhat
200
+
201
+ @fhat.setter
202
+ def fhat(self, value):
203
+ if value is not None:
204
+ if not (
205
+ isinstance(value, np.ndarray)
206
+ and value.dtype == np.complex128
207
+ and value.flags["C"]
208
+ ):
209
+ raise RuntimeError(
210
+ "fhat has to be C-continuous, numpy complex128 array"
211
+ )
212
+ Ns = np.prod(self.N)
213
+ _nfftlib.jnfft_set_fhat.restype = np.ctypeslib.ndpointer(
214
+ np.complex128, ndim=1, shape=Ns, flags="C"
215
+ )
216
+ self._fhat = _nfftlib.jnfft_set_fhat(self.plan, value)
217
+
218
+ @property
219
+ def num_threads(self):
220
+ return _nfftlib.nfft_get_num_threads()
221
+
222
+ def nfft_trafo(self):
223
+ """
224
+ Computes the NDFT using the fast NFFT algorithm for the provided nodes in **x** and coefficients in **fhat**.
225
+ """
226
+ _nfftlib.jnfft_trafo.restype = np.ctypeslib.ndpointer(
227
+ np.complex128, shape=self.M, flags="C"
228
+ )
229
+ # Prevent bad stuff from happening
230
+ if self.finalized:
231
+ raise RuntimeError("NFFT already finalized")
232
+
233
+ if not hasattr(self, "fhat"):
234
+ raise ValueError("fhat has not been set.")
235
+
236
+ if not hasattr(self, "x"):
237
+ raise ValueError("x has not been set.")
238
+
239
+ ptr = _nfftlib.jnfft_trafo(self.plan)
240
+ self.f = ptr
241
+
242
+ def trafo(self):
243
+ """
244
+ Alternative call for **nfft_trafo()**
245
+ """
246
+ return self.nfft_trafo()
247
+
248
+ def nfft_trafo_direct(self):
249
+ """
250
+ Computes the NDFT via naive matrix-vector multiplication for the provided nodes in **x** and coefficients in **fhat**.
251
+ """
252
+ _nfftlib.jnfft_trafo_direct.restype = np.ctypeslib.ndpointer(
253
+ np.complex128, shape=self.M, flags="C"
254
+ )
255
+ # Prevent bad stuff from happening
256
+ if self.finalized:
257
+ raise RuntimeError("NFFT already finalized")
258
+
259
+ if self.fhat is None:
260
+ raise ValueError("fhat has not been set.")
261
+
262
+ if self.x is None:
263
+ raise ValueError("x has not been set.")
264
+
265
+ ptr = _nfftlib.jnfft_trafo_direct(self.plan)
266
+ self.f = ptr
267
+
268
+ def trafo_direct(self):
269
+ """
270
+ Alternative call for **nfft_trafo_direct()**
271
+ """
272
+ return self.nfft_trafo_direct()
273
+
274
+ def nfft_adjoint(self):
275
+ """
276
+ Computes the adjoint NDFT using the fast adjoint NFFT algorithm for the provided nodes in **x** and coefficients in **f**.
277
+ """
278
+ Ns = np.prod(self.N)
279
+ _nfftlib.jnfft_adjoint.restype = np.ctypeslib.ndpointer(
280
+ np.complex128, shape=Ns, flags="C"
281
+ )
282
+ # Prevent bad stuff from happening
283
+ if self.finalized:
284
+ raise RuntimeError("NFFT already finalized")
285
+
286
+ if not hasattr(self, "f"):
287
+ raise ValueError("f has not been set.")
288
+
289
+ if not hasattr(self, "x"):
290
+ raise ValueError("x has not been set.")
291
+
292
+ ptr = _nfftlib.jnfft_adjoint(self.plan)
293
+ self.fhat = ptr
294
+
295
+ def adjoint(self):
296
+ """
297
+ Alternative call for **nfft_adjoint()**
298
+ """
299
+ return self.nfft_adjoint()
300
+
301
+ def nfft_adjoint_direct(self):
302
+ """
303
+ Computes the adjoint NDFT using naive matrix-vector multiplication for the provided nodes in **x** and coefficients in **f**.
304
+ """
305
+ Ns = np.prod(self.N)
306
+ _nfftlib.jnfft_adjoint_direct.restype = np.ctypeslib.ndpointer(
307
+ np.complex128, shape=Ns, flags="C"
308
+ )
309
+ # Prevent bad stuff from happening
310
+ if self.finalized:
311
+ raise RuntimeError("NFFT already finalized")
312
+
313
+ if not hasattr(self, "f"):
314
+ raise ValueError("f has not been set.")
315
+
316
+ if not hasattr(self, "x"):
317
+ raise ValueError("x has not been set.")
318
+
319
+ ptr = _nfftlib.jnfft_adjoint_direct(self.plan)
320
+ self.fhat = ptr
321
+
322
+ def adjoint_direct(self):
323
+ """
324
+ Alternative call for **nfft_adjoint_direct()**
325
+ """
326
+ return self.nfft_adjoint_direct()
pyNFFT3/NFMT.py ADDED
@@ -0,0 +1 @@
1
+ # TODO: Add Python equivalent of NFMT.jl