Skip to content

--remove-stripe-method vo-all collapses reconstruction to a constant on full-volume batches of highly-attenuating samples #83

Description

@decarlof

Summary

vo-all stripe removal, applied to the full-row range of a densely-absorbing sample, produces a reconstruction where every in-FOV voxel is a single constant (~2.4e-4) and every out-of-FOV voxel is 0 — no sample structure visible. Bug is independent of --vo-all-la-size (tested 51, 61, 201, all produce the same collapse). Row subsets of the same dataset reconstruct correctly. Switching to --remove-stripe-method fw on the same command produces a correct reconstr
uction.

Steps to reproduce

Dataset: cast_LM10_FS0_s2_5x_Cu2_118.h5 (2-BM, 1801 projections, 2426×3232 detector, transmission ratio ~0.26 — heavily absorbing).

tomocupy recon_steps \
  --file-name <raw.h5> \
  --rotation-axis-auto auto --rotation-axis-method vo \
  --reconstruction-type full \
  --propagation-distance 200 --fbp-filter shepp \
  --pixel-size 1.4 --energy 30 \
  --retrieve-phase-method paganin --retrieve-phase-alpha 0.001 \
  --remove-stripe-method vo-all \
  --flat-linear True

Expected behavior

Normal Paganin-processed reconstruction with values in the ±0.05 range and visible sample structure (like the fw output confirms is possible on this dataset).

Actual behavior

/exchange/data has correct shape (2426, 3232, 3232) float32, correct file size, no crash, no warnings in the log. But the numerical content is:

  • In-FOV voxels: all ≈ 2.3929265e-4 (44,743 distinct values in a 5×10⁻⁷ range around this constant — essentially a plateau)
  • Out-of-FOV voxels: exactly 0
  • No sample structure visible; renders as a uniform white disk

Bisect showing row-range dependence

Same command with different --start-row / --end-row:

range rows outcome mid-slice max
0..1213 1213 OK 0.0144
1213..2426 1213 BROKEN 2.4e-4
600..1800 1200 BROKEN 2.4e-4
1213..1500 287 BROKEN 4.4e-4 (different constant)
1500..1800 300 BROKEN 2.4e-4
1800..2426 626 BROKEN 2.4e-4
1400..1500 100 OK 0.0026

Rows 1500..1800 have raw row-mean 138–172 vs the volume median of 410 — those rows are heavily attenuated (sample dominates the FOV). This appears to be the trigger content for vo-all's collapse.

Independence from --vo-all-la-size

Tested with --vo-all-la-size 51 (below default 61) and with 201 (user's original). Both produce the same collapsed constant. Bug is not in the filter-window sizing; it's in vo-all's core estimation logic on this input class.

Fix / workaround

Switch to --remove-stripe-method fw. Same command otherwise. Produces a correct full-volume reconstruction (values −0.038 to +0.053, sample structure visible).

Suspected root cause

vo-all's stripe estimation likely uses a global reduction across z-rows. When the batch includes rows where the sample dominates the FOV (dim raw signal), the estimator produces a corrupt "stripe" pattern that's actually the sample profile itself. That correction, when applied globally to all rows in the batch, cancels out the reconstruction, collapsing all in-FOV voxels to a constant. Row subsets that avoid the problematic z-band reconstruct fine.

Would need to inspect remove_stripe._rs_large3 / _rs_dead3 and their handling of very low mean row-intensity to confirm.

Environment

  • tomocupy 1.1.0 installed from decarlof/tomocupy fork main branch (which is upstream + a few decarlof-specific fixes; no vo-all-related fork changes)
  • cupy 12.3, CUDA 12.1 (system)
  • Linux, tomo4 at APS 2-BM
  • HDF5_USE_FILE_LOCKING=FALSE (NFS output dir; unrelated to this bug)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions