Skip to content
Back to skills

Ct Z Stack Orientation Flip

ASecurity

Detect inverted CT slice ordering by comparing ImagePositionPatient[2] (the Z coordinate) of the first and last DICOM slice in a series, flipping the volume along axis 0 when needed so every patient ends up in canonical head→feet order

  • 61 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 12, 2026
toolspython

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add wenmin-wu/ds-skills --skill ct-z-stack-orientation-flip --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ct Z Stack Orientation Flip?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ct Z Stack Orientation Flip
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wenmin-wu-ct-z-stack-orientation-flip/badge)](https://www.skillsdirectory.com/skills/wenmin-wu-ct-z-stack-orientation-flip)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cv-ct-z-stack-orientation-flip
description: Detect inverted CT slice ordering by comparing ImagePositionPatient[2] (the Z coordinate) of the first and last DICOM slice in a series, flipping the volume along axis 0 when needed so every patient ends up in canonical head→feet order
---

## Overview

DICOM file names are not a reliable proxy for slice order. The same scanner can write `1.dcm` as the topmost slice on one acquisition and the bottommost on the next, depending on protocol and reconstruction direction. If you train on a mix and don't normalize, augmentations like `flip(axis=0)` become silently inconsistent and the model learns a much fuzzier through-plane signal than it could. The single-line fix: read `ImagePositionPatient[2]` from the first and last DICOM in the series; if the last has a *larger* Z value than the first, the stack is inverted relative to the canonical patient frame and you flip it.

## Quick Start

```python
import dicomsdl
import numpy as np

def canonicalize_z_order(image, dcm_dir, slice_min, slice_max):
    dcm0 = dicomsdl.open(f'{dcm_dir}/{slice_min}.dcm')
    dcmN = dicomsdl.open(f'{dcm_dir}/{slice_max - 1}.dcm')
    z0 = dcm0.ImagePositionPatient[2]
    zN = dcmN.ImagePositionPatient[2]

    if zN > z0:                       # inverted: flip into head→feet order
        image = image[::-1]

    dz = abs((zN - z0) / max(slice_max - slice_min - 1, 1))
    return np.ascontiguousarray(image), dz
```

## Workflow

1. After loading every slice into a `(D, H, W)` array (in filename order), open just the first and last DICOM headers
2. Compare `ImagePositionPatient[2]` — the third element is the Z coordinate in patient space
3. If `zN > z0`, the stack is in feet→head order; reverse it with `image[::-1]`
4. Compute `dz` as the absolute difference divided by `(num_slices - 1)` and store it for the resampling step
5. `np.ascontiguousarray` after the slice-reverse to avoid downstream `RuntimeError: non-contiguous` from torch

## Key Decisions

- **Compare Z, not InstanceNumber**: InstanceNumber can be reset, missing, or inconsistent across vendors; ImagePositionPatient is the geometric ground truth.
- **Absolute `dz`**: after flipping, the sign is meaningless — what the resampler needs is the magnitude.
- **Only open two DICOMs, not all of them**: the orientation check costs ~1ms and avoids re-parsing every header.
- **`np.ascontiguousarray` after `[::-1]`**: numpy reverse-views are non-contiguous and break torch tensor zero-copy paths.
- **Don't sort by Z to "fix" ordering**: just flipping is faster and equivalent for evenly-spaced acquisitions, which is what 99% of CT series are.

## References

- [LB 0.55 — 2.5D + 3D sample model](https://www.kaggle.com/competitions/rsna-2023-abdominal-trauma-detection)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…