pcSENSE¶
template <typename T1> class pcSENSE
Phase-corrected multi-shot SENSE operator.
Extends the standard SENSE model with per-shot phase maps to correct for inter-shot phase inconsistencies in multi-shot non-Cartesian acquisitions. Uses a per-shot Gdft encoding operator to handle arbitrary trajectories.
The per-shot phase-corrected forward model is:
where \(P_s = e^{i\phi_s(\mathbf{r})}\) is the shot-specific phase map for shot \(s\), and \(G_s\) is the encoding operator for that shot's k-space trajectory.
Forward (per coil, per shot):
graph LR
X["$$\mathbf{x}$$"] --> P["$$P_s \circ \mathbf{x}$$"]
P --> S["$$S_c \circ$$"]
S --> G["$$G_s$$"]
G --> D["$$\mathbf{d}_{c,s}$$"]
Adjoint (combine all coils and shots):
graph RL
D["$$\mathbf{d}_{c,s}$$"] --> GH["$$G_s^H$$"]
GH --> SC["$$S_c^* \circ$$"]
SC --> PC["$$P_s^* \circ$$"]
PC --> SUM["$$\sum_{c,s}$$"]
SUM --> XH["$$\hat{\mathbf{x}}$$"]
The adjoint sums over all coils and shots:
Unlike SENSE, which assumes a single k-space trajectory for all data, pcSENSE handles multi-shot acquisitions (e.g., diffusion-weighted imaging) where each shot has a different \(B_0\)-induced phase error. This is essential for techniques such as navigated multi-shot DWI with non-Cartesian sampling.
// Per-shot k-space coordinates concatenated, readout times, maps
pcSENSE<float> P(kx, ky, kz, Nx, Ny, Nz, nc, tvec,
SENSEmap, fieldMap, shotPhaseMap);
Col<cx_float> kdata = P * image; // forward
Col<cx_float> recon = P / kdata; // adjoint
See : Liu, Moseley & Bammer, "Simultaneous phase correction and SENSE reconstruction for navigated multi-shot DWI with non-cartesian k-space sampling," MRM, 2005. https://doi.org/10.1002/mrm.20706
See : Holtrop & Sutton, "High spatial resolution diffusion weighted imaging on clinical 3T MRI scanners using multislab spiral acquisitions," J Med Imaging, 2016. https://doi.org/10.1117/1.JMI.3.2.023501
See : SENSE
See : pcSenseTimeSeg
T1
: Floating-point precision type (float or double).
Variables¶
| Name | Description |
|---|---|
| Nd | Number of k-space samples per shot. |
| Ni | Number of image pixels. |
| Nc | Number of receiver coils. |
| Ns | Number of shots. |
| SMap | Coil sensitivity maps, size Ni x Nc (single source of truth, GPU-ready). |
| conjSMap | Conjugate sensitivity maps, size Ni x Nc. |
| PMap | Per-shot phase maps in radians, size Ni x Ns. |
| expiPMap | Complex exponential of phase maps (exp(i*PMap)), size Ni x Ns. |
| conjExpiPMap | Conjugate complex exponential of phase maps (exp(-i*PMap)), size Ni x Ns. |
| FMap | Off-resonance field map (rad/s), length Ni. |
| Kx | k-space x-coordinates matrix, size (samples/shot) x Ns. |
| Ky | k-space y-coordinates matrix, size (samples/shot) x Ns. |
| Kz | k-space z-coordinates matrix, size (samples/shot) x Ns. |
| Tvec | Readout time vector (s), size (samples/shot) x Ns. |
| Nx | Image size in x. |
| Ny | Image size in y. |
| Nz | Image size in z. |
| Ix | Image-space x-coordinates, length Ni. |
| Iy | Image-space y-coordinates, length Ni. |
| Iz | Image-space z-coordinates, length Ni. |
| i | Imaginary unit constant for phase computations. |
| type | Interpolation type: 1 = Hanning, 2 = exact min-max. |
| L | Number of time segments for field-map correction. |
| combinedMap_gpu | Array of per-shot encoding operator pointers. |
| conjCombinedMap_gpu | Conjugate combined maps for adjoint. |
| combinedMapCols | Precomputed per-(coil,shot) combined maps SMap.col(ii) % exp(+i*PMap.col(jj)), stored as independent page-aligned forgeCol columns for zero-copy Metal weighting. Index col = jj + ii * Ns (matches the k-space column layout and the CUDA combinedMap_gpu convention). |
| conjCombinedMapCols | Conjugate counterparts for the adjoint (exp(-i*PMap) weighting). |
Operators¶
| Name | Description |
|---|---|
| operator* | Forward phase-corrected SENSE transform: image -> k-space. d : Input image vector of length Ni. Return : Stacked k-space vector of length NdNsNc. |
| operator/ | Adjoint phase-corrected SENSE transform: k-space -> image. d : Input k-space vector of length NdNsNc. Return : Output image vector of length Ni. |
| operator* | Forward phase-corrected SENSE transform (forgeCol overload for Metal path). |
| operator/ | Adjoint phase-corrected SENSE transform (forgeCol overload for Metal path). |
Functions¶
| Name | Description |
|---|---|
| pcSENSE | Default constructor. |
| ~pcSENSE | Destructor โ frees per-shot Gdft encoding operator array. |
| pcSENSE | Construct a phase-corrected SENSE operator. |
Variable Details¶
FMap¶
Col<T1> FMap
Off-resonance field map (rad/s), length Ni.
Ix¶
Col<T1> Ix
Image-space x-coordinates, length Ni.
Iy¶
Col<T1> Iy
Image-space y-coordinates, length Ni.
Iz¶
Col<T1> Iz
Image-space z-coordinates, length Ni.
Kx¶
Mat<T1> Kx
k-space x-coordinates matrix, size (samples/shot) x Ns.
Ky¶
Mat<T1> Ky
k-space y-coordinates matrix, size (samples/shot) x Ns.
Kz¶
Mat<T1> Kz
k-space z-coordinates matrix, size (samples/shot) x Ns.
L¶
uword L
Number of time segments for field-map correction.
Nc¶
uword Nc
Number of receiver coils.
Nd¶
uword Nd
Number of k-space samples per shot.
Ni¶
uword Ni
Number of image pixels.
Ns¶
uword Ns
Number of shots.
Nx¶
uword Nx
Image size in x.
Ny¶
uword Ny
Image size in y.
Nz¶
uword Nz
Image size in z.
PMap¶
Mat<T1> PMap
Per-shot phase maps in radians, size Ni x Ns.
SMap¶
forgeMat<forgeComplex<T1>> SMap
Coil sensitivity maps, size Ni x Nc (single source of truth, GPU-ready).
Tvec¶
Mat<T1> Tvec
Readout time vector (s), size (samples/shot) x Ns.
combinedMapCols¶
std::vector<forgeCol<forgeComplex<T1>>> combinedMapCols
Precomputed per-(coil,shot) combined maps SMap.col(ii) % exp(+i*PMap.col(jj)), stored as independent page-aligned forgeCol columns for zero-copy Metal weighting. Index col = jj + ii * Ns (matches the k-space column layout and the CUDA combinedMap_gpu convention).
combinedMap_gpu¶
std::vector<forgeCol<forgeComplex<T1>>> combinedMap_gpu
Array of per-shot encoding operator pointers. Per-shot per-coil combined (SMap * expiPMap) maps, pre-uploaded to GPU. Index: jj + ii * Ns (shots vary faster than coils).
conjCombinedMapCols¶
std::vector<forgeCol<forgeComplex<T1>>> conjCombinedMapCols
Conjugate counterparts for the adjoint (exp(-i*PMap) weighting).
conjCombinedMap_gpu¶
std::vector<forgeCol<forgeComplex<T1>>> conjCombinedMap_gpu
Conjugate combined maps for adjoint.
conjExpiPMap¶
forgeMat<forgeComplex<T1>> conjExpiPMap
Conjugate complex exponential of phase maps (exp(-i*PMap)), size Ni x Ns.
conjSMap¶
forgeMat<forgeComplex<T1>> conjSMap
Conjugate sensitivity maps, size Ni x Nc.
expiPMap¶
forgeMat<forgeComplex<T1>> expiPMap
Complex exponential of phase maps (exp(i*PMap)), size Ni x Ns.
i¶
CxT1 i
Imaginary unit constant for phase computations.
type¶
uword type
Interpolation type: 1 = Hanning, 2 = exact min-max.
Operator Details¶
operator*¶
Col<CxT1> operator*(const Col<CxT1>& d) const
Forward phase-corrected SENSE transform: image -> k-space.
d
: Input image vector of length Ni.
Return : Stacked k-space vector of length NdNsNc.
forgeCol<forgeComplex<T1>> operator*(const forgeCol<forgeComplex<T1>>& d) const
Forward phase-corrected SENSE transform (forgeCol overload for Metal path).
d
: Input image vector of length Ni.
Return : Stacked k-space vector of length NdNsNc.
operator/¶
Col<CxT1> operator/(const Col<CxT1>& d) const
Adjoint phase-corrected SENSE transform: k-space -> image.
d
: Input k-space vector of length NdNsNc.
Return : Output image vector of length Ni.
forgeCol<forgeComplex<T1>> operator/(const forgeCol<forgeComplex<T1>>& d) const
Adjoint phase-corrected SENSE transform (forgeCol overload for Metal path).
d
: Input k-space vector of length NdNsNc.
Return : Output image vector of length Ni.
Function Details¶
pcSENSE¶
pcSENSE()
Default constructor.
pcSENSE(Col<T1> kx, Col<T1> ky, Col<T1> kz, uword nx, uword ny, uword nz, uword nc, Col<T1> t, Col<CxT1> SENSEmap, Col<T1> FieldMap, Col<T1> ShotPhaseMap)
Construct a phase-corrected SENSE operator.
kx
: k-space x-coordinates (all shots concatenated), length Nd*Ns.
ky
: k-space y-coordinates, length Nd*Ns.
kz
: k-space z-coordinates, length Nd*Ns.
nx
: Image size in x.
ny
: Image size in y.
nz
: Image size in z.
nc
: Number of receiver coils.
t
: Per-sample readout time vector (s), length Nd*Ns.
SENSEmap
: Sensitivity maps as flat vector, length Ni*Nc.
FieldMap
: Off-resonance field map (rad/s), length Ni.
ShotPhaseMap
: Per-shot phase maps in radians, length Ni*Ns.
~pcSENSE¶
~pcSENSE()
Destructor โ frees per-shot Gdft encoding operator array.