pcSenseTimeSeg¶
template <typename T1> class pcSenseTimeSeg
Phase-corrected multi-shot SENSE with time-segmented field-map correction.
Combines per-shot phase correction (pcSENSE) with time-segmented off-resonance correction (TimeSegmentation), providing accurate forward and adjoint models for multi-shot non-Cartesian acquisitions with significant \(B_0\) inhomogeneity. This is the full model for techniques such as multi-shot spiral DWI.
The combined forward model applies shot-varying phase correction and time-segmented field correction together:
where \(A_s\) is the time-segmented NUFFT operator for shot \(s\) (which incorporates the off-resonance field map \(\omega(\mathbf{r})\)), \(P_s = e^{i\phi_s(\mathbf{r})}\) is the shot-specific phase map, and \(S_c\) is the coil sensitivity map.
When to use: - Use this operator when both shot-varying phase correction AND off-resonance field correction are needed (e.g., multi-shot spiral diffusion-weighted imaging). - If only phase correction is needed (short readouts, minimal off-resonance), use pcSENSE instead. - If only field correction is needed (single-shot acquisition with off-resonance), use TimeSegmentation wrapping SENSE.
pcSenseTimeSeg<float> P(kx, ky, kz, Nx, Ny, Nz, nc, tvec,
L, interpType, SENSEmap, fieldMap,
shotPhaseMap);
Col<cx_float> kdata = P * image; // forward
Col<cx_float> recon = P / kdata; // adjoint
See : pcSENSE
See : TimeSegmentation
See : SENSE
T1
: Floating-point precision type (float or double).
Variables¶
| Name | Description |
|---|---|
| SMap | Number of k-space samples per shot. |
| PMap | Per-shot phase maps in radians, size Ni x Ns. |
| FMap | Off-resonance field map (rad/s), length Ni. |
| Kx | k-space x-coordinates, size (samples/shot) x Ns. |
| Ky | k-space y-coordinates, size (samples/shot) x Ns. |
| Kz | k-space z-coordinates, 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 = min-max. |
| L | Number of time segments for field-map correction. |
| shotSpecificSenseMap | Shot-specific combined (sensitivity x phase) maps, size Ni x (Nc*Ns). |
| conjShotSpecificSenseMap | Conjugate shot-specific maps, size Ni x (Nc*Ns). |
| coilChunk | Coils per batched pipeline call (memory-aware; see forge_metal_coil_chunk). |
| shotSenseMapCols | Persistent page-aligned combined (sensitivity x shot-phase) maps, one forgeCol of length Ni per (shot, coil), [shot][coil] layout: index jjNc + coil. This layout (rather than shotSpecificSenseMap's native jj + coilNs column order) makes a coil chunk within one shot contiguous, matching TimeSegmentation::forwardBatchedWeighted's mapFirst..mapFirst+count window. Standalone forgeCol allocations (not forgeMat::col() views), so every entry is independently page-aligned for zero-copy Metal dispatch. |
| conjShotSenseMapCols | Conjugate counterpart of shotSenseMapCols (adjoint weighting), same [shot][coil] layout. |
| adjSliceBufs | Persistent page-aligned per-coil k-space slice buffers for the batched adjoint gather (coilChunk buffers of length Nd, reused across PCG iterations and shots). |
| shotSenseMap_gpu | Per-shot combined sensitivity+phase maps, pre-uploaded to GPU (Ns*Nc vectors). |
| conjShotSenseMap_gpu | Conjugate per-shot maps for adjoint, pre-uploaded to GPU. |
| coilChunk | Coils per batched TimeSegmentation call. |
| cudaFwdStack | Persistent CUDA scratch for operatoroperator/(forgeCol), sized to coilChunk (the per-call coil batch) and allocated once in the constructor, then reused by every PCG iteration instead of being cudaMallocAsync'd/cudaFreeAsync'd per call -- see cuda/c4-shared-batching Task 3b. |
Operators¶
| Name | Description |
|---|---|
| operator* | Forward transform: image -> k-space with phase and field-map correction. d : Input image vector of length Ni. Return : Stacked k-space vector of length NdNsNc. |
| operator/ | Adjoint transform: k-space -> image with phase and field-map correction. d : Input k-space vector of length NdNsNc. Return : Output image vector of length Ni. |
| operator* | Forward transform (forgeCol overload for Metal path). |
| operator/ | Adjoint transform (forgeCol overload for Metal path). |
Functions¶
| Name | Description |
|---|---|
| pcSenseTimeSeg | Default constructor. |
| ~pcSenseTimeSeg | Destructor — frees per-shot NUFFT and TimeSegmentation operator arrays. |
| pcSenseTimeSeg | Array of per-shot NUFFT operator pointers. |
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, size (samples/shot) x Ns.
Ky¶
Mat<T1> Ky
k-space y-coordinates, size (samples/shot) x Ns.
Kz¶
Mat<T1> Kz
k-space z-coordinates, size (samples/shot) x Ns.
L¶
uword L
Number of time segments for field-map correction.
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¶
Mat<CxT1> SMap
Number of k-space samples per shot.
Number of image pixels.
Number of receiver coils.
Number of shots.
Coil sensitivity maps, size Ni x Nc.
Tvec¶
Mat<T1> Tvec
Readout time vector (s), size (samples/shot) x Ns.
adjSliceBufs¶
mutable std::vector<forgeCol<forgeComplex<T1>>> adjSliceBufs
Persistent page-aligned per-coil k-space slice buffers for the
batched adjoint gather (coilChunk buffers of length Nd, reused across
PCG iterations and shots).
coilChunk¶
uword coilChunk
Coils per batched pipeline call (memory-aware; see forge_metal_coil_chunk).
coilChunk¶
uword coilChunk
Coils per batched TimeSegmentation call. Default (single-slice, the
C2-era behavior): always 1. Opt-in via FORGE_CUDA_BATCHED_OPERATORS=1
(see cuda_batched_operators_enabled() in pcSenseTimeSeg.cpp): the
memory-aware chunk size from forge_cuda_coil_chunk.
conjShotSenseMapCols¶
std::vector<forgeCol<forgeComplex<T1>>> conjShotSenseMapCols
Conjugate counterpart of shotSenseMapCols (adjoint weighting), same
[shot][coil] layout.
conjShotSenseMap_gpu¶
std::vector<forgeCol<forgeComplex<T1>>> conjShotSenseMap_gpu
Conjugate per-shot maps for adjoint, pre-uploaded to GPU.
conjShotSpecificSenseMap¶
Mat<CxT1> conjShotSpecificSenseMap
Conjugate shot-specific maps, size Ni x (Nc*Ns).
cudaFwdStack¶
mutable forgeCol<forgeComplex<T1>> cudaFwdStack
Persistent CUDA scratch for operatoroperator/(forgeCol), sized to
coilChunk (the per-call coil batch) and allocated once in the
constructor, then reused by every PCG iteration instead of being
cudaMallocAsync'd/cudaFreeAsync'd per call -- see
cuda/c4-shared-batching Task 3b.
i¶
CxT1 i
Imaginary unit constant for phase computations.
shotSenseMapCols¶
std::vector<forgeCol<forgeComplex<T1>>> shotSenseMapCols
Persistent page-aligned combined (sensitivity x shot-phase) maps, one
forgeCol of length Ni per (shot, coil), [shot][coil] layout: index
jj*Nc + coil. This layout (rather than shotSpecificSenseMap's native
jj + coil*Ns column order) makes a coil chunk within one shot
contiguous, matching TimeSegmentation::forwardBatchedWeighted's
mapFirst..mapFirst+count window. Standalone forgeCol allocations (not
forgeMat::col() views), so every entry is independently page-aligned
for zero-copy Metal dispatch.
shotSenseMap_gpu¶
std::vector<forgeCol<forgeComplex<T1>>> shotSenseMap_gpu
Per-shot combined sensitivity+phase maps, pre-uploaded to GPU (Ns*Nc vectors).
shotSpecificSenseMap¶
Mat<CxT1> shotSpecificSenseMap
Shot-specific combined (sensitivity x phase) maps, size Ni x (Nc*Ns).
type¶
uword type
Interpolation type: 1 = Hanning, 2 = min-max.
Operator Details¶
operator*¶
Col<CxT1> operator*(const Col<CxT1>& d) const
Forward transform: image -> k-space with phase and field-map correction.
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 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 transform: k-space -> image with phase and field-map correction.
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 transform (forgeCol overload for Metal path).
d
: Input k-space vector of length NdNsNc.
Return : Output image vector of length Ni.
Function Details¶
pcSenseTimeSeg¶
pcSenseTimeSeg()
Default constructor.
pcSenseTimeSeg(Col<T1> kx, Col<T1> ky, Col<T1> kz, uword nx, uword ny, uword nz, uword nc, Col<T1> t, uword L, uword intType, Col<CxT1> SENSEmap, Col<T1> FieldMap, Col<T1> ShotPhaseMap, T1 gridOS = (T1)1.6)
Array of per-shot NUFFT operator pointers.
Array of per-shot TimeSegmentation operator pointers.
Construct a phase-corrected SENSE+time-segmentation operator.
kx
: k-space x-coordinates (all shots), 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 (s), length Nd*Ns.
L
: Number of time segments.
intType
: Interpolation type: 1 = Hanning, 2 = min-max.
SENSEmap
: Sensitivity maps, flat vector length Ni*Nc.
FieldMap
: Off-resonance field map (rad/s), length Ni.
ShotPhaseMap
: Per-shot phase maps (rad), length Ni*Ns.
gridOS
: NUFFT grid oversampling factor (default 1.6, set by
the post-fftshift-fold FFT-size study: fastest OS
that passes both the operator-level <1% qualification
bar and end-to-end NRMSE parity vs the former OS 2.0
default). Sizes with only factors of 2 and 3 run
fastest on the Metal MPSGraph FFT (radix-5 sizes are
slower).
~pcSenseTimeSeg¶
~pcSenseTimeSeg()
Destructor — frees per-shot NUFFT and TimeSegmentation operator arrays.