-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* FastFourierOp and PadOp added
- Loading branch information
Showing
14 changed files
with
412 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
"""Class for Fast Fourier Operator.""" | ||
|
||
# Copyright 2023 Physikalisch-Technische Bundesanstalt | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import torch | ||
|
||
from mrpro.operators import LinearOperator | ||
from mrpro.operators import ZeroPadOp | ||
|
||
|
||
class FastFourierOp(LinearOperator): | ||
"""Fast Fourier operator class.""" | ||
|
||
def __init__( | ||
self, | ||
dim: tuple[int, ...] = (-3, -2, -1), | ||
recon_shape: tuple[int, ...] | None = None, | ||
encoding_shape: tuple[int, ...] | None = None, | ||
) -> None: | ||
"""Fast Fourier Operator class. | ||
Remark regarding the fftshift/ifftshift: | ||
fftshift shifts the zero-frequency point to the center of the data, ifftshift undoes this operation. | ||
The input to both forward and ajoint assumes that the zero-frequency is in the center of the data. | ||
Torch.fft.fftn and torch.fft.ifftn expect the zero-frequency to be the first entry in the tensor. | ||
Therefore for forward and ajoint first ifftshift needs to be applied, then fftn or ifftn and then ifftshift. | ||
Parameters | ||
---------- | ||
dim, optional | ||
dim along which FFT and IFFT are applied, by default last three dimensions (-1, -2, -3) | ||
encoding_shape, optional | ||
shape of encoded data | ||
recon_shape, optional | ||
shape of reconstructed data | ||
""" | ||
super().__init__() | ||
self._dim: tuple[int, ...] = dim | ||
self._pad_op: ZeroPadOp | ||
if encoding_shape is not None and recon_shape is not None: | ||
self._pad_op = ZeroPadOp(dim=dim, orig_shape=recon_shape, padded_shape=encoding_shape) | ||
else: | ||
# No padding | ||
self._pad_op = ZeroPadOp(dim=(), orig_shape=(), padded_shape=()) | ||
|
||
def forward(self, x: torch.Tensor) -> torch.Tensor: | ||
"""FFT from image space to k-space. | ||
Parameters | ||
---------- | ||
x | ||
image data on Cartesian grid | ||
Returns | ||
------- | ||
FFT of x | ||
""" | ||
return torch.fft.fftshift( | ||
torch.fft.fftn(torch.fft.ifftshift(self._pad_op.forward(x), dim=self._dim), dim=self._dim, norm='ortho'), | ||
dim=self._dim, | ||
) | ||
|
||
def adjoint(self, y: torch.Tensor) -> torch.Tensor: | ||
"""IFFT from k-space to image space. | ||
Parameters | ||
---------- | ||
y | ||
k-space data on Cartesian grid | ||
Returns | ||
------- | ||
IFFT of y | ||
""" | ||
# FFT | ||
return self._pad_op.adjoint( | ||
torch.fft.fftshift( | ||
torch.fft.ifftn(torch.fft.ifftshift(y, dim=self._dim), dim=self._dim, norm='ortho'), dim=self._dim | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
"""Class for Zero Pad Operator.""" | ||
|
||
# Copyright 2023 Physikalisch-Technische Bundesanstalt | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import torch | ||
|
||
from mrpro.operators import LinearOperator | ||
from mrpro.utils import zero_pad_or_crop | ||
|
||
|
||
class ZeroPadOp(LinearOperator): | ||
"""Zero Pad operator class.""" | ||
|
||
def __init__( | ||
self, | ||
dim: tuple[int, ...], | ||
orig_shape: tuple[int, ...], | ||
padded_shape: tuple[int, ...], | ||
) -> None: | ||
"""Zero Pad Operator class. | ||
The operator carries out zero-padding if the padded_shape is larger than orig_shape and cropping if the | ||
padded_shape is smaller. | ||
Parameters | ||
---------- | ||
dim | ||
dim along which padding should be applied | ||
orig_shape | ||
shape of original data along dim, same length as dim | ||
padded_shape | ||
shape of padded data along dim, same length as dim | ||
""" | ||
if len(dim) != len(orig_shape) or len(dim) != len(padded_shape): | ||
raise ValueError('Dim, orig_shape and padded_shape have to be of same length') | ||
|
||
super().__init__() | ||
self.dim: tuple[int, ...] = dim | ||
self.orig_shape: tuple[int, ...] = orig_shape | ||
self.padded_shape: tuple[int, ...] = padded_shape | ||
|
||
def forward(self, x: torch.Tensor) -> torch.Tensor: | ||
"""Pad or crop data. | ||
Parameters | ||
---------- | ||
x | ||
data with shape orig_shape | ||
Returns | ||
------- | ||
data with shape padded_shape | ||
""" | ||
return zero_pad_or_crop(x, self.padded_shape, self.dim) | ||
|
||
def adjoint(self, x: torch.Tensor) -> torch.Tensor: | ||
"""Crop or pad data. | ||
Parameters | ||
---------- | ||
x | ||
data with shape padded_shape | ||
Returns | ||
------- | ||
data with shape orig_shape | ||
""" | ||
return zero_pad_or_crop(x, self.orig_shape, self.dim) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from mrpro.utils._smap import smap | ||
from mrpro.utils._remove_repeat import remove_repeat | ||
from mrpro.utils._rgetattr import rgetattr | ||
from mrpro.utils._zero_pad_or_crop import zero_pad_or_crop |
Oops, something went wrong.