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 |
|---|---|
| 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. |
| 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.
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¶
Mat<CxT1> SMap
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 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.
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.