An image coordinate system is the rule that says where (0,0,0) sits and which way the axes run, so a voxel in an array can be a millimetre in a patient. In medical volumes that rule is usually LPS or RAS for anatomy, plus a pixel / ijk index for the file. It is not “what a cross-section is.” It is not CT window/level. It is not a PYCAD product.
If you meant axial / sagittal / coronal as named planes → cross-section analysis. If you meant window width / window level → window width vs window level. If you meant opening the file in Slicer or ITK-SNAP → visualize and annotate DICOM / NIfTI. If you meant how a gantry makes the volume → acquisition of images.
PYCAD builds custom web DICOM viewers and imaging models. A viewer has to honour the affine or the overlay lands on the wrong vertebra. That is the imaging piece. It is not a coordinate-system SKU.
Three frames, one volume
A CT or MRI is not a PNG. The array is a stack of numbers. The patient is a body on a table. The scanner has its own detector axes. You need all three, and you need the transform that maps one onto another.
| Frame | Origin | Axes | Who uses it |
|---|---|---|---|
| Pixel / ijk (index) | First stored voxel, usually a corner of the array | i, j, k along the file. NumPy is often (z, y, x) | Code. Crop, resample, a U-Net that never saw millimetres |
| LPS (Left–Posterior–Superior) | A point in the patient, often the scanner’s image-position tag | +x left, +y posterior, +z superior | DICOM. Most CT/MR vendors (Siemens, Philips, many others) |
| RAS (Right–Anterior–Superior) | Same patient, different handedness on x and y | +x right, +y anterior, +z superior | 3D Slicer internally. Some GE / research NIfTI |
LPS and RAS agree on +z (toward the head). They flip x and y. Mixing them without a flip is how a left lung becomes a right lung in a mesh. Slicer’s coordinate-systems note is the short reference: Slicer is RAS inside and treats incoming DICOM as LPS unless the file says otherwise.
Pixel is not millimetre
In a 2D photograph the “matrix” convention is origin at the top-left, +x right, +y down — the way a buffer is stored. Graphics APIs often put +y up. That fight matters for a screenshot. It is the wrong fight for a CT.
A medical volume adds:
- Spacing. Voxel size in millimetres (DICOM
PixelSpacing+SliceThickness/SpacingBetweenSlices). Anisotropic slices are normal. A 0.5 × 0.5 × 3 mm chest CT is not a cube. - Origin. DICOM
ImagePositionPatient— the LPS (usually) coordinate of the first voxel of that slice. - Orientation. DICOM
ImageOrientationPatient— two direction cosines (row and column). The slice normal is their cross product. Oblique acquisitions are not a bug; they are a rotated frame.
Those three numbers — origin, direction, spacing — are the affine. Apply it and ijk becomes a point in the patient. Drop it and you have a pretty cube that does not match the next visit, the RT structure set, or the surgical tracker.
LPS vs RAS, in one sentence
Both are anatomical frames: they name patient left/right, not “screen left.” DICOM’s patient-based coordinate system is LPS (see DICOM PS3.3 C.7.6.2, Image Position / Orientation). NIfTI can be either; the qform/sform codes say which. Slicer converts LPS DICOM into RAS for its scene. ITK is LPS. nibabel reports whatever the header stored — read the affine, do not assume.
A world / scanner frame also exists (the gantry, the room). Registration and IGS trackers live there. This page is the image file. Surgical navigation as a procedure is imaging guided surgery.
What breaks when you ignore it
- Left/right. A RAS array displayed as LPS, or a flip on save. Always look at a known landmark (liver on the right in LPS axial, radiological convention) before you trust a mask.
- A 3D model that does not sit on the CT. STL exporters that dump ijk as millimetres. The mesh is stretched by spacing and shifted by origin.
- A crop that moved the origin and did not write a new affine. SimpleITK and sitk will, if you keep the metadata. NumPy slicing will not. The crop how-to is fast medical imaging cropping.
- A model trained on (z,y,x) PNG stacks. Inference on a DICOM series without reorient-to-canonical is a different volume. nnU-Net and MONAI spend a lot of code on this on purpose.
A practical check
- Print the affine (nibabel
img.affine, SimpleITKGetOrigin/GetDirection/GetSpacing). - Map voxel (0,0,0) and voxel (last, last, last) into LPS. Do those points sit where the anatomy says they should?
- If you must resample to 1 mm isotropic, resample the image and the affine, not the array alone.
3D Slicer shows all three frames in the Transforms / Volumes modules if you want to see the matrices instead of trusting a printout.
What this page is not
- Not 689. Planes and “what a slice is” already live on cross-section analysis.
- Not 686. Window/level and HU are display, not a coordinate frame.
- Not astronomy, GIS, Wolfram matrix-vs-graphics, or a self-driving-car lecture. Those sections were Outrank padding. The medical job is LPS / RAS / ijk.
- Not a PYCAD coordinate toolkit. IBM, NVIDIA, and Outrank stills are gone.
If a clinic app has to hang a DICOM volume with the overlay on the correct side, that is the imaging piece. Case studies.