-
Notifications
You must be signed in to change notification settings - Fork 3
/
DirectReconstruction.py
85 lines (72 loc) · 3.09 KB
/
DirectReconstruction.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""Direct Reconstruction by Adjoint Fourier Transform."""
from collections.abc import Callable
from mrpro.algorithms.reconstruction.Reconstruction import Reconstruction
from mrpro.data._kdata.KData import KData
from mrpro.data.CsmData import CsmData
from mrpro.data.DcfData import DcfData
from mrpro.data.IData import IData
from mrpro.data.KNoise import KNoise
from mrpro.operators.FourierOp import FourierOp
from mrpro.operators.LinearOperator import LinearOperator
class DirectReconstruction(Reconstruction):
"""Direct Reconstruction by Adjoint Fourier Transform."""
def __init__(
self,
kdata: KData | None = None,
fourier_op: LinearOperator | None = None,
csm: Callable[[IData], CsmData] | CsmData | None = CsmData.from_idata_walsh,
noise: KNoise | None = None,
dcf: DcfData | None = None,
):
"""Initialize DirectReconstruction.
Parameters
----------
kdata
KData. If kdata is provided and fourier_op or dcf are None, then fourier_op and dcf are estimated based on
kdata. Otherwise fourier_op and dcf are used as provided.
fourier_op
Instance of the FourierOperator used for reconstruction. If None, set up based on kdata.
csm
Sensitivity maps for coil combination. If None, no coil combination is carried out, i.e. images for each
coil are returned. If a callable is provided, coil images are reconstructed using the adjoint of the
FourierOperator (including density compensation) and then sensitivity maps are calculated using the
callable. For this, kdata needs also to be provided. For examples have a look at the CsmData class
e.g. from_idata_walsh or from_idata_inati.
noise
KNoise used for prewhitening. If None, no prewhitening is performed
dcf
K-space sampling density compensation. If None, set up based on kdata.
Raises
------
ValueError
If the kdata and fourier_op are None or if csm is a Callable but kdata is None.
"""
super().__init__()
if fourier_op is None:
if kdata is None:
raise ValueError('Either kdata or fourier_op needs to be defined.')
self.fourier_op = FourierOp.from_kdata(kdata)
else:
self.fourier_op = fourier_op
if kdata is not None and dcf is None:
self.dcf = DcfData.from_traj_voronoi(kdata.traj)
else:
self.dcf = dcf
self.noise = noise
if csm is None or isinstance(csm, CsmData):
self.csm = csm
else:
if kdata is None:
raise ValueError('kdata needs to be defined to calculate the sensitivity maps.')
self.recalculate_csm(kdata, csm)
def forward(self, kdata: KData) -> IData:
"""Apply the reconstruction.
Parameters
----------
kdata
k-space data to reconstruct.
Returns
-------
the reconstruced image.
"""
return self.direct_reconstruction(kdata)