From 885f12f721d1ca67df2390a0462399bc2bec85ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Schr=C3=B6ter?= Date: Tue, 24 Feb 2026 11:17:33 +0100 Subject: [PATCH 1/6] fixed index_set helper function --- src/pyGroupedTransforms/NFCTtools.py | 3 +-- src/pyGroupedTransforms/NFFTtools.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pyGroupedTransforms/NFCTtools.py b/src/pyGroupedTransforms/NFCTtools.py index c85628a..716a76a 100644 --- a/src/pyGroupedTransforms/NFCTtools.py +++ b/src/pyGroupedTransforms/NFCTtools.py @@ -77,8 +77,7 @@ def nfct_index_set( if d == 1: return np.array([i for i in range(0, bandwidths[0])], "int") - bandwidths = bandwidths[::-1] - tmp = tuple([list(range(0, bw)) for bw in bandwidths]) + tmp = tuple([list(range(0, bw)) for bw in bandwidths[::-1]]) tmp = itertools.product(*(tmp[::-1])) freq = np.empty((d, np.prod(bandwidths)), dtype=int) diff --git a/src/pyGroupedTransforms/NFFTtools.py b/src/pyGroupedTransforms/NFFTtools.py index 43f4f3c..9c211a4 100644 --- a/src/pyGroupedTransforms/NFFTtools.py +++ b/src/pyGroupedTransforms/NFFTtools.py @@ -87,8 +87,9 @@ def nfft_index_set( return np.array( list(range(int(-bandwidths[0] / 2), int(bandwidths[0] / 2))), dtype="int" ) - - tmp = [list(range(int(-bw / 2), int(bw / 2))) for bw in bandwidths] + + + tmp = [list(range(int(-bw / 2), int(bw / 2))) for bw in bandwidths[::-1]] tmp = itertools.product(*(tmp[::-1])) freq = np.empty((d, np.prod(bandwidths)), dtype=int) @@ -134,7 +135,6 @@ def get_transform( # Output: * `F::LinearMap{ComplexF64}` ... Linear map of the Fourier-transform implemented by the NFFT """ - if bandwidths.ndim > 1 or bandwidths.dtype != "int32": return "Please use an zero or one-dimensional numpy.array with dtype 'int32' as input" From 8f1b01d028a609e6d83aac7c2b48e23fe3cfa9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Schr=C3=B6ter?= Date: Tue, 24 Feb 2026 11:18:38 +0100 Subject: [PATCH 2/6] version 1.1.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f02cdf2..2596536 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "pyGroupedTransforms" -version = "1.0.0" +version = "1.1.0" authors = [ { name="Felix Wirth", email="fwi012001@gmail.com" }, ] From d1901838808501da72293acdf2c8c00ecc82348d Mon Sep 17 00:00:00 2001 From: passscoed Date: Tue, 24 Feb 2026 10:19:31 +0000 Subject: [PATCH 3/6] Auto code format --- src/pyGroupedTransforms/NFCTtools.py | 2 +- src/pyGroupedTransforms/NFFTtools.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pyGroupedTransforms/NFCTtools.py b/src/pyGroupedTransforms/NFCTtools.py index 716a76a..99efef7 100644 --- a/src/pyGroupedTransforms/NFCTtools.py +++ b/src/pyGroupedTransforms/NFCTtools.py @@ -126,7 +126,7 @@ def get_transform( if bandwidths.ndim > 1 or bandwidths.dtype != "int32": return "Please use an zero or one-dimensional numpy.array with dtype 'int32' as input" - (M, d) = X.shape + M, d = X.shape if len(bandwidths) == 0: return DeferredLinearOperator( diff --git a/src/pyGroupedTransforms/NFFTtools.py b/src/pyGroupedTransforms/NFFTtools.py index 9c211a4..2237e87 100644 --- a/src/pyGroupedTransforms/NFFTtools.py +++ b/src/pyGroupedTransforms/NFFTtools.py @@ -87,8 +87,7 @@ def nfft_index_set( return np.array( list(range(int(-bandwidths[0] / 2), int(bandwidths[0] / 2))), dtype="int" ) - - + tmp = [list(range(int(-bw / 2), int(bw / 2))) for bw in bandwidths[::-1]] tmp = itertools.product(*(tmp[::-1])) @@ -138,7 +137,7 @@ def get_transform( if bandwidths.ndim > 1 or bandwidths.dtype != "int32": return "Please use an zero or one-dimensional numpy.array with dtype 'int32' as input" - (M, d) = np.shape(X) + M, d = np.shape(X) if len(bandwidths) == 0: return DeferredLinearOperator( From 6dae0d0984fcfe6e0cc7d541d6fc726e677cd19f Mon Sep 17 00:00:00 2001 From: Lucas Teixeira Date: Mon, 6 Jul 2026 17:46:53 +0200 Subject: [PATCH 4/6] feat: add keops algorithm --- src/pyGroupedTransforms/GroupedTransform.py | 56 ++++++++++++--- src/pyGroupedTransforms/NFFTtools.py | 78 +++++++++++++++++++++ 2 files changed, 124 insertions(+), 10 deletions(-) diff --git a/src/pyGroupedTransforms/GroupedTransform.py b/src/pyGroupedTransforms/GroupedTransform.py index 4f4117b..76ed90d 100644 --- a/src/pyGroupedTransforms/GroupedTransform.py +++ b/src/pyGroupedTransforms/GroupedTransform.py @@ -183,7 +183,7 @@ def __init__( system, X, settings=[], - fastmult=True, + algorithm="nfft", parallel=True, basis_vect=[], N=[], @@ -227,9 +227,9 @@ def __init__( ) if system in {"chui1", "chui2", "chui3", "chui4"}: - fastmult = True + algorithm = "nfft" - self.fastmult = fastmult + self.algorithm = algorithm self.basis_vect = basis_vect self.system = system self.X = X @@ -240,7 +240,7 @@ def __init__( else: self.settings = settings - if fastmult: + if algorithm == "nfft": self.matrix = np.empty((0, 0), dtype=object) self.transforms = [ DeferredLinearOperator() for i in range(len(self.settings)) @@ -265,6 +265,25 @@ def __init__( self.transforms[idx] = s.mode.get_transform( bandwidths=s.bandwidths, X=np.copy(X[:, u], order="C") ) + elif algorithm == "keops": + self.matrix = np.empty((0,0), dtype=object) + + self.transforms = [ + DeferredLinearOperator() + for _ in range(len(self.settings)) + ] + + for idx, s in enumerate(self.settings): + + if len(s.bandwidths) == 0: + u = (0,) + else: + u = s.u + + self.transforms[idx] = s.mode.get_transform_keops( + bandwidths=s.bandwidths, + X=np.copy(X[:,u], order="C") + ) else: self.transforms = [] s1 = self.settings[0] @@ -321,9 +340,8 @@ def __mul__(self, other): If other (= f) is an numpy.ndarray, this function overloads the * notation in order to achieve the adjoint transform `f = F*f`. """ - if isinstance(other, np.ndarray): # `f = F*f` (f = other) - if self.fastmult: + if self.algorithm == "nfft": fhat = GroupedCoefficients(self.settings) def adjoint_worker(i): @@ -345,17 +363,26 @@ def adjoint_worker(i): adjoint_worker(i) return fhat - else: + elif self.algorithm == "keops": + fhat = GroupedCoefficients(self.settings) + + for i in range(len(self.transforms)): + adjoint_result = self.transforms[i].H @ other + fhat[self.settings[i].u] = adjoint_result + + return fhat + elif self.algorithm == "direct": return GroupedCoefficients( self.settings, (self.matrix.conj()).T @ other ) + elif isinstance(other, GC): # `f = F*fhat` (fhat = other) if self.settings != other.settings: raise ValueError( "The GroupedTransform and the GroupedCoefficients have different settings" ) - if self.fastmult: + if self.algorithm == "nfft": results = [] def worker(i): @@ -376,7 +403,16 @@ def worker(i): worker(i) return sum(results) - else: + elif self.algorithm == "keops": + results = [] + + for i in range(len(self.transforms)): + u = self.settings[i].u + result = self.transforms[i] @ other[u] + results.append(result) + + return sum(results) + elif self.algorithm == "direct": return self.matrix @ other.data else: raise ValueError("Wrong input data type") @@ -412,7 +448,7 @@ def __getitem__(self, u): if idx is None: raise ValueError("This term is not contained") - elif self.fastmult: + elif self.algorithm == "nfft": return self.transforms[idx] else: return self.get_matrix() diff --git a/src/pyGroupedTransforms/NFFTtools.py b/src/pyGroupedTransforms/NFFTtools.py index 2237e87..10872ae 100644 --- a/src/pyGroupedTransforms/NFFTtools.py +++ b/src/pyGroupedTransforms/NFFTtools.py @@ -2,6 +2,10 @@ from pyGroupedTransforms import * +import torch +import pykeops +from pykeops.torch import LazyTensor + def datalength( bandwidths: np.ndarray, @@ -168,6 +172,80 @@ def adjoint(f): # function adjoint(f::Vector{ComplexF64})::Vector{ComplexF64} return DeferredLinearOperator( dtype=np.complex128, shape=(M, N), mfunc=trafo, rmfunc=adjoint ) + +def get_transform_keops( + bandwidths: np.array, X: np.array +): + if bandwidths.ndim > 1 or bandwidths.dtype != "int32": + return "Please use an zero or one-dimensional numpy.array with dtype 'int32' as input" + + M, d = np.shape(X) + + if len(bandwidths) == 0: + return DeferredLinearOperator( + dtype=np.complex128, + shape=(M, 1), + mfunc=lambda fhat: np.full(M, fhat[0]), + rmfunc=lambda f: np.array([np.sum(f)]), + ) + + X_torch = torch.tensor(X, dtype=torch.float64, device="cuda") + freq = index_set_without_zeros( + np.array(bandwidths, dtype=np.int32) + ).T + + I_torch = torch.tensor( + freq, + dtype=torch.float64, + device="cuda" + ) + + + def trafo(fhat): + X_i = LazyTensor(X_torch[:, None, :].contiguous()) + K_j = LazyTensor(I_torch[None, :, :].contiguous()) + phase_fwd = (X_i * K_j).sum(-1) + two_pi_phase = -2 * torch.pi * phase_fwd + kernel_fwd = two_pi_phase.cos() + 1j * two_pi_phase.sin() + fhat_torch = torch.tensor(fhat, dtype=torch.complex128, device="cuda") + fhat_j = LazyTensor(fhat_torch[None, :, None].contiguous()) + + try: + result = (kernel_fwd * fhat_j).sum(dim=1) + torch.cuda.synchronize() + result = result.squeeze().cpu().numpy() + return result + except Exception as e: + print("Error in KeOps trafo:", e) + return None + + def adjoint(f): + f_torch = torch.tensor(f, dtype=torch.complex128, device="cuda").contiguous() + + X_i = LazyTensor(X_torch[None, :, :].contiguous()) + K_j = LazyTensor(I_torch[:, None, :].contiguous()) + + phase = (K_j * X_i).sum(-1) + kernel = (-2*torch.pi*phase).cos() - 1j*(-2*torch.pi*phase).sin() + + f_i = LazyTensor(f_torch[None, :, None].contiguous()) + + try: + result = (kernel * f_i).sum(dim=1) + torch.cuda.synchronize() + result = result.squeeze().cpu().numpy() + + return result + except Exception as e: + print("Error in KeOps adjoint:", e) + return None + + + Ncoeffs = np.prod(bandwidths - 1) + + return DeferredLinearOperator( + dtype=np.complex128, shape=(M, Ncoeffs), mfunc=trafo, rmfunc=adjoint + ) def get_matrix( From e6abf47bea87edd16e581ceaf1c73e059bed5c28 Mon Sep 17 00:00:00 2001 From: Lucas Teixeira Date: Wed, 8 Jul 2026 16:45:12 +0200 Subject: [PATCH 5/6] feat: add keops full matrix multiplication --- src/pyGroupedTransforms/GroupedTransform.py | 118 +++++++++++++++----- src/pyGroupedTransforms/NFFTtools.py | 75 ------------- 2 files changed, 89 insertions(+), 104 deletions(-) diff --git a/src/pyGroupedTransforms/GroupedTransform.py b/src/pyGroupedTransforms/GroupedTransform.py index 76ed90d..57bf99a 100644 --- a/src/pyGroupedTransforms/GroupedTransform.py +++ b/src/pyGroupedTransforms/GroupedTransform.py @@ -1,6 +1,12 @@ import numpy as np +import torch from pyGroupedTransforms import * +from .NFFTtools import index_set_without_zeros + +import pykeops +from pykeops.torch import LazyTensor + # All code that is linked to NFMTtools or to system = "mixed" is not tested yet.... @@ -266,24 +272,87 @@ def __init__( bandwidths=s.bandwidths, X=np.copy(X[:, u], order="C") ) elif algorithm == "keops": - self.matrix = np.empty((0,0), dtype=object) + self.matrix = np.empty((0,0), dtype=object) + + self.transforms = [ + DeferredLinearOperator() + for _ in range(len(self.settings)) + ] + + D = X.shape[1] - self.transforms = [ - DeferredLinearOperator() - for _ in range(len(self.settings)) - ] + freq_list = [] - for idx, s in enumerate(self.settings): + for s in self.settings: - if len(s.bandwidths) == 0: - u = (0,) - else: - u = s.u + if len(s.bandwidths) == 0: + full = np.zeros((1, D), dtype=np.int32) + + + else: + local = index_set_without_zeros( + np.array(s.bandwidths, dtype=np.int32) + ).T + + full = np.zeros((local.shape[0], D), dtype=np.int32) + + for i, dim in enumerate(s.u): + full[:, dim] = local[:, i] + + freq_list.append(full) + + freq = np.vstack(freq_list) + + X_torch = torch.tensor(X, dtype=torch.float64, device="cuda") + I_torch = torch.tensor( + freq, + dtype=torch.float64, + device="cuda" + ) + + def trafo(fhat): + X_i = LazyTensor(X_torch[:, None, :].contiguous()) + K_j = LazyTensor(I_torch[None, :, :].contiguous()) + phase_fwd = (X_i * K_j).sum(-1) + two_pi_phase = -2 * torch.pi * phase_fwd + kernel_fwd = two_pi_phase.cos() + 1j * two_pi_phase.sin() + fhat_torch = torch.tensor(fhat, dtype=torch.complex128, device="cuda") + fhat_j = LazyTensor(fhat_torch[None, :, None].contiguous()) + + try: + result = (kernel_fwd * fhat_j).sum(dim=1) + torch.cuda.synchronize() + result = result.squeeze().cpu().numpy() + return result + except Exception as e: + print("Error in KeOps trafo:", e) + return None + + def adjoint(f): + f_torch = torch.tensor(f, dtype=torch.complex128, device="cuda").contiguous() + + X_i = LazyTensor(X_torch[None, :, :].contiguous()) + K_j = LazyTensor(I_torch[:, None, :].contiguous()) - self.transforms[idx] = s.mode.get_transform_keops( - bandwidths=s.bandwidths, - X=np.copy(X[:,u], order="C") - ) + phase = (K_j * X_i).sum(-1) + kernel = (-2*torch.pi*phase).cos() - 1j*(-2*torch.pi*phase).sin() + + f_i = LazyTensor(f_torch[None, :, None].contiguous()) + + try: + result = (kernel * f_i).sum(dim=1) + torch.cuda.synchronize() + result = result.squeeze().cpu().numpy() + + return result + except Exception as e: + print("Error in KeOps adjoint:", e) + return None + + self.transforms = [DeferredLinearOperator( + dtype=np.complex128, shape=(X.shape[0], len(freq)), mfunc=trafo, rmfunc=adjoint + )] + else: self.transforms = [] s1 = self.settings[0] @@ -363,14 +432,10 @@ def adjoint_worker(i): adjoint_worker(i) return fhat + elif self.algorithm == "keops": - fhat = GroupedCoefficients(self.settings) - - for i in range(len(self.transforms)): - adjoint_result = self.transforms[i].H @ other - fhat[self.settings[i].u] = adjoint_result - - return fhat + return GroupedCoefficients(self.settings, self.transforms[0].H @ other) + elif self.algorithm == "direct": return GroupedCoefficients( self.settings, (self.matrix.conj()).T @ other @@ -403,15 +468,10 @@ def worker(i): worker(i) return sum(results) + elif self.algorithm == "keops": - results = [] - - for i in range(len(self.transforms)): - u = self.settings[i].u - result = self.transforms[i] @ other[u] - results.append(result) - - return sum(results) + return self.transforms[0] @ other.data + elif self.algorithm == "direct": return self.matrix @ other.data else: diff --git a/src/pyGroupedTransforms/NFFTtools.py b/src/pyGroupedTransforms/NFFTtools.py index 10872ae..d0b02c6 100644 --- a/src/pyGroupedTransforms/NFFTtools.py +++ b/src/pyGroupedTransforms/NFFTtools.py @@ -172,81 +172,6 @@ def adjoint(f): # function adjoint(f::Vector{ComplexF64})::Vector{ComplexF64} return DeferredLinearOperator( dtype=np.complex128, shape=(M, N), mfunc=trafo, rmfunc=adjoint ) - -def get_transform_keops( - bandwidths: np.array, X: np.array -): - if bandwidths.ndim > 1 or bandwidths.dtype != "int32": - return "Please use an zero or one-dimensional numpy.array with dtype 'int32' as input" - - M, d = np.shape(X) - - if len(bandwidths) == 0: - return DeferredLinearOperator( - dtype=np.complex128, - shape=(M, 1), - mfunc=lambda fhat: np.full(M, fhat[0]), - rmfunc=lambda f: np.array([np.sum(f)]), - ) - - X_torch = torch.tensor(X, dtype=torch.float64, device="cuda") - freq = index_set_without_zeros( - np.array(bandwidths, dtype=np.int32) - ).T - - I_torch = torch.tensor( - freq, - dtype=torch.float64, - device="cuda" - ) - - - def trafo(fhat): - X_i = LazyTensor(X_torch[:, None, :].contiguous()) - K_j = LazyTensor(I_torch[None, :, :].contiguous()) - phase_fwd = (X_i * K_j).sum(-1) - two_pi_phase = -2 * torch.pi * phase_fwd - kernel_fwd = two_pi_phase.cos() + 1j * two_pi_phase.sin() - fhat_torch = torch.tensor(fhat, dtype=torch.complex128, device="cuda") - fhat_j = LazyTensor(fhat_torch[None, :, None].contiguous()) - - try: - result = (kernel_fwd * fhat_j).sum(dim=1) - torch.cuda.synchronize() - result = result.squeeze().cpu().numpy() - return result - except Exception as e: - print("Error in KeOps trafo:", e) - return None - - def adjoint(f): - f_torch = torch.tensor(f, dtype=torch.complex128, device="cuda").contiguous() - - X_i = LazyTensor(X_torch[None, :, :].contiguous()) - K_j = LazyTensor(I_torch[:, None, :].contiguous()) - - phase = (K_j * X_i).sum(-1) - kernel = (-2*torch.pi*phase).cos() - 1j*(-2*torch.pi*phase).sin() - - f_i = LazyTensor(f_torch[None, :, None].contiguous()) - - try: - result = (kernel * f_i).sum(dim=1) - torch.cuda.synchronize() - result = result.squeeze().cpu().numpy() - - return result - except Exception as e: - print("Error in KeOps adjoint:", e) - return None - - - Ncoeffs = np.prod(bandwidths - 1) - - return DeferredLinearOperator( - dtype=np.complex128, shape=(M, Ncoeffs), mfunc=trafo, rmfunc=adjoint - ) - def get_matrix( bandwidths, X From 7b370f9a82e729b2ab62615bccb5dd8b5656da6c Mon Sep 17 00:00:00 2001 From: texlucas Date: Wed, 8 Jul 2026 14:45:39 +0000 Subject: [PATCH 6/6] Auto code format --- src/pyGroupedTransforms/GroupedTransform.py | 72 +++++++++++---------- src/pyGroupedTransforms/NFFTtools.py | 8 +-- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/pyGroupedTransforms/GroupedTransform.py b/src/pyGroupedTransforms/GroupedTransform.py index 57bf99a..da40e01 100644 --- a/src/pyGroupedTransforms/GroupedTransform.py +++ b/src/pyGroupedTransforms/GroupedTransform.py @@ -1,12 +1,11 @@ import numpy as np +import pykeops import torch +from pykeops.torch import LazyTensor from pyGroupedTransforms import * -from .NFFTtools import index_set_without_zeros - -import pykeops -from pykeops.torch import LazyTensor +from .NFFTtools import index_set_without_zeros # All code that is linked to NFMTtools or to system = "mixed" is not tested yet.... @@ -272,13 +271,12 @@ def __init__( bandwidths=s.bandwidths, X=np.copy(X[:, u], order="C") ) elif algorithm == "keops": - self.matrix = np.empty((0,0), dtype=object) - + self.matrix = np.empty((0, 0), dtype=object) + self.transforms = [ - DeferredLinearOperator() - for _ in range(len(self.settings)) + DeferredLinearOperator() for _ in range(len(self.settings)) ] - + D = X.shape[1] freq_list = [] @@ -287,9 +285,8 @@ def __init__( if len(s.bandwidths) == 0: full = np.zeros((1, D), dtype=np.int32) - - - else: + + else: local = index_set_without_zeros( np.array(s.bandwidths, dtype=np.int32) ).T @@ -302,15 +299,11 @@ def __init__( freq_list.append(full) freq = np.vstack(freq_list) - + X_torch = torch.tensor(X, dtype=torch.float64, device="cuda") - I_torch = torch.tensor( - freq, - dtype=torch.float64, - device="cuda" - ) - - def trafo(fhat): + I_torch = torch.tensor(freq, dtype=torch.float64, device="cuda") + + def trafo(fhat): X_i = LazyTensor(X_torch[:, None, :].contiguous()) K_j = LazyTensor(I_torch[None, :, :].contiguous()) phase_fwd = (X_i * K_j).sum(-1) @@ -327,15 +320,19 @@ def trafo(fhat): except Exception as e: print("Error in KeOps trafo:", e) return None - + def adjoint(f): - f_torch = torch.tensor(f, dtype=torch.complex128, device="cuda").contiguous() - + f_torch = torch.tensor( + f, dtype=torch.complex128, device="cuda" + ).contiguous() + X_i = LazyTensor(X_torch[None, :, :].contiguous()) K_j = LazyTensor(I_torch[:, None, :].contiguous()) phase = (K_j * X_i).sum(-1) - kernel = (-2*torch.pi*phase).cos() - 1j*(-2*torch.pi*phase).sin() + kernel = (-2 * torch.pi * phase).cos() - 1j * ( + -2 * torch.pi * phase + ).sin() f_i = LazyTensor(f_torch[None, :, None].contiguous()) @@ -343,16 +340,21 @@ def adjoint(f): result = (kernel * f_i).sum(dim=1) torch.cuda.synchronize() result = result.squeeze().cpu().numpy() - + return result except Exception as e: print("Error in KeOps adjoint:", e) return None - self.transforms = [DeferredLinearOperator( - dtype=np.complex128, shape=(X.shape[0], len(freq)), mfunc=trafo, rmfunc=adjoint - )] - + self.transforms = [ + DeferredLinearOperator( + dtype=np.complex128, + shape=(X.shape[0], len(freq)), + mfunc=trafo, + rmfunc=adjoint, + ) + ] + else: self.transforms = [] s1 = self.settings[0] @@ -432,15 +434,15 @@ def adjoint_worker(i): adjoint_worker(i) return fhat - + elif self.algorithm == "keops": - return GroupedCoefficients(self.settings, self.transforms[0].H @ other) - + return GroupedCoefficients(self.settings, self.transforms[0].H @ other) + elif self.algorithm == "direct": return GroupedCoefficients( self.settings, (self.matrix.conj()).T @ other ) - + elif isinstance(other, GC): # `f = F*fhat` (fhat = other) if self.settings != other.settings: raise ValueError( @@ -468,10 +470,10 @@ def worker(i): worker(i) return sum(results) - + elif self.algorithm == "keops": return self.transforms[0] @ other.data - + elif self.algorithm == "direct": return self.matrix @ other.data else: diff --git a/src/pyGroupedTransforms/NFFTtools.py b/src/pyGroupedTransforms/NFFTtools.py index d0b02c6..432ac47 100644 --- a/src/pyGroupedTransforms/NFFTtools.py +++ b/src/pyGroupedTransforms/NFFTtools.py @@ -1,11 +1,10 @@ import numpy as np - -from pyGroupedTransforms import * - -import torch import pykeops +import torch from pykeops.torch import LazyTensor +from pyGroupedTransforms import * + def datalength( bandwidths: np.ndarray, @@ -173,6 +172,7 @@ def adjoint(f): # function adjoint(f::Vector{ComplexF64})::Vector{ComplexF64} dtype=np.complex128, shape=(M, N), mfunc=trafo, rmfunc=adjoint ) + def get_matrix( bandwidths, X ): # get_matrix(bandwidths::Vector{Int}, X::Array{Float64})::Array{ComplexF64}