Fix: deg/rad unit mismatch in removeProjections corrupts chunked helical FBP - #214
Open
zezisme wants to merge 1 commit into
Open
Fix: deg/rad unit mismatch in removeProjections corrupts chunked helical FBP#214zezisme wants to merge 1 commit into
zezisme wants to merge 1 commit into
Conversation
…cal FBP ### Bug Summary In helical cone-beam FBP, when the projection + volume data exceed GPU memory, LEAP triggers `backproject_FBP_multiGPU_splitViews`, which creates per-chunk parameter copies via `removeProjections()`. Two bugs in this function caused incorrect reconstruction values: **Bug 1 (Major): phis_full stored in degrees, consumed as radians** `removeProjections()` calls `get_angles(phis_full)` to save the full-scan angle array. `get_angles()` converts from internal radians to degrees: phis_full[i] = (phis[i] + 0.5*PI) * 180.0 / PI Later, `T_phi()` preferentially reads `phis_full` over `phis`: if (phis_full != NULL) phis_local = phis_full; // ← uses degrees! Since `T_phi()` returns angular step without deg→rad conversion, and `FBPscalar ∝ T_phi()`, the normalization applied during Hilbert filtering is scaled by 180/π ≈ 57.3×. The derivative kernel (`parallelRay_derivative`) uses `phis[]` (always radians) for its local T_phi, so the 1/T_phi and ×T_phi do NOT cancel — the error propagates directly to reconstructed CT values. **Bug 2 (Minor): phi_start/phi_end restored to full-scan range** After `set_angles()`, `phi_start`/`phi_end` correctly reflect the chunk's angular range, but are immediately restored to full-scan values: phi_start = phi_start_save; // full-scan phi_end = phi_end_save; These are copied to GPU constant memory (`d_phi_start`, `d_phi_end`) and used in the helical weighted backprojector kernel to bound the redundancy `sumWeights` computation. With full-scan bounds, `sumWeights` includes turns not present in the chunk's data, causing incorrect per-view normalization. ### Repro Conditions - Helical cone-beam scan (pitch ≠ 0) - Projection data + volume data exceed `available_GPU_memory` (triggers `backproject_FBP_multiGPU_splitViews`) - Example: 6000 views × 505 rows × 2063 cols = 23.3 GiB, vol 1527³ × 445 = 3.9 GiB, required ≈ 50.7 GiB > typical 48 GB GPU → triggered Small datasets that fit entirely on GPU are NOT affected (no chunking, `phis_full` remains NULL, `T_phi()` uses `phis[]` in radians). ### Verification FBPscalar can be printed before FBP (via `get_FBPscalar()`) to verify: FBPscalar = 1/(2π) × T_φ × pixW × (sod/sdd)² × pixH / (voxW² × voxH) With the fix, `FBPscalar ≈ 0.03–0.04` for typical micro-CT geometries (corresponding to T_φ ≈ 0.004 rad). Before the fix, chunked FBP would report the same FBPscalar value (computed from the pre-chunk params), but internally use a 57× larger value for each chunk. ### Files Changed - `src/parameters.cpp`: `removeProjections()` — store `phis_full` in radians, manually set `phis` and `phi_start`/`phi_end` without degree-expecting `set_angles()`.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug Summary
In helical cone-beam FBP, when the projection + volume data exceed GPU memory, LEAP triggers
backproject_FBP_multiGPU_splitViews, which creates per-chunk parameter copies viaremoveProjections(). Two bugs in this function caused incorrect reconstruction values:Bug 1 (Major): phis_full stored in degrees, consumed as radians
removeProjections()callsget_angles(phis_full)to save the full-scan angle array.get_angles()converts from internal radians to degrees:phis_full[i] = (phis[i] + 0.5*PI) * 180.0 / PI
Later,
T_phi()preferentially readsphis_fulloverphis:if (phis_full != NULL) phis_local = phis_full; // ← uses degrees!
Since
T_phi()returns angular step without deg→rad conversion, andFBPscalar ∝ T_phi(), the normalization applied during Hilbert filtering is scaled by 180/π ≈ 57.3×. The derivative kernel (parallelRay_derivative) usesphis[](always radians) for its local T_phi, so the 1/T_phi and ×T_phi do NOT cancel — the error propagates directly to reconstructed CT values.Bug 2 (Minor): phi_start/phi_end restored to full-scan range
After
set_angles(),phi_start/phi_endcorrectly reflect the chunk's angular range, but are immediately restored to full-scan values:phi_start = phi_start_save; // full-scan
phi_end = phi_end_save;
These are copied to GPU constant memory (
d_phi_start,d_phi_end) and used in the helical weighted backprojector kernel to bound the redundancysumWeightscomputation. With full-scan bounds,sumWeightsincludes turns not present in the chunk's data, causing incorrect per-view normalization.Repro Conditions
available_GPU_memory(triggersbackproject_FBP_multiGPU_splitViews)Small datasets that fit entirely on GPU are NOT affected (no chunking,
phis_fullremains NULL,T_phi()usesphis[]in radians).Verification
FBPscalar can be printed before FBP (via
get_FBPscalar()) to verify:FBPscalar = 1/(2π) × T_φ × pixW × (sod/sdd)² × pixH / (voxW² × voxH)
With the fix,
FBPscalar ≈ 0.03–0.04for typical micro-CT geometries (corresponding to T_φ ≈ 0.004 rad). Before the fix, chunked FBP would report the same FBPscalar value (computed from the pre-chunk params), but internally use a 57× larger value for each chunk.Files Changed
src/parameters.cpp:removeProjections()— storephis_fullin radians, manually setphisandphi_start/phi_endwithout degree-expectingset_angles().