Parse CSA header information from Siemens MRI acquisitions with Python.
Some Siemens MRI scans may include CSA headers that provide valuable information about the acquisition and storage of the data. These headers are stored as private data elements, usually looking something like:
(0029, 1010) CSA Image Header Type OB: 'IMAGE NUM 4'
(0029, 1010) CSA Image Header Version OB: '20100114'
(0029, 1010) CSA Image Header Info OB: Array of 11560 bytes
(0029, 1020) CSA Series Header Type OB: 'MR'
(0029, 1020) CSA Series Header Version OB: '20100114'
(0029, 1020) CSA Series Header Info OB: Array of 80248 bytes
The CSA Image Header Info and CSA Series Header Info elements contain encoded information which is crucial for the correct interpretation of the associated acquisition data.
For a detailed explanation on the CSA encoding scheme, please see this excellent article from NiBabel's documentation site.
- Fast and Lightweight: Minimal dependencies (numpy, pydicom)
- Comprehensive Parsing: Supports both CSA header types (Type 1 and Type 2)
- ASCCONV Support: Automatic parsing of embedded ASCCONV protocol parameters
- Type-Safe: Complete type hints for all public APIs
- Well-Tested: 96% test coverage with 161 tests
- Python 3.9+: Modern Python with support through Python 3.13
- NiBabel Compatible: Integrates seamlessly with neuroimaging workflows
Table of Contents
- Features
- Installation
- Quickstart
- Advanced Usage
- Integration with NiBabel
- Examples
- Tests
- Contributing
- Citation
- License
pip install csa_headerFor working with the provided examples and automatic example data downloading:
pip install csa_header[examples]This installs:
nibabelfor NiBabel integration examplespoochfor automatic downloading of example DICOM files
For development (includes pre-commit hooks and IPython):
pip install csa_header[dev]The quickest way to get started is using the built-in example data:
>>> # Install with examples support
>>> # pip install csa_header[examples]
>>>
>>> from csa_header.examples import fetch_example_dicom
>>> from csa_header import CsaHeader
>>> import pydicom
>>>
>>> # Fetch example DICOM (downloads once, then cached)
>>> dicom_path = fetch_example_dicom()
>>> dcm = pydicom.dcmread(dicom_path)
>>>
>>> # Parse CSA Series Header
>>> raw_csa = dcm[(0x29, 0x1020)].value
>>> parsed_csa = CsaHeader(raw_csa).read()
>>> len(parsed_csa)
79The example file is an anonymized Siemens MPRAGE scan hosted on Zenodo:
Use pydicom to read a DICOM header:
>>> import pydicom
>>> dcm = pydicom.dcmread("/path/to/file.dcm")Extract a data element containing a CSA header, e.g., for CSA Series Header Info:
>>> data_element = dcm.get((0x29, 0x1020))
>>> data_element
(0029, 1020) [CSA Series Header Info] OB: Array of 180076 elementsRead the raw byte array from the data element:
>>> raw_csa = data_element.value
>>> raw_csa
b'SV10\x04\x03\x02\x01O\x00\x00\x00M\x00\x00\x00UsedPatientWeight\x00 <Visible> "true" \n \n <ParamStr\x01\x00\x00\x00IS\x00\x00\x06...'Parse the contents of the CSA header with the CsaHeader class:
>>> from csa_header import CsaHeader
>>> parsed_csa = CsaHeader(raw_csa).read()
>>> parsed_csa
{
'NumberOfPrescans': {'index': 1, 'VR': 'IS', 'VM': 1, 'value': 0},
'TransmitterCalibration': {'index': 2, 'VR': 'DS', 'VM': 1, 'value': 247.102},
'PhaseGradientAmplitude': {'index': 3, 'VR': 'DS', 'VM': 1, 'value': 0.0},
'ReadoutGradientAmplitude': {'index': 4, 'VR': 'DS', 'VM': 1, 'value': 0.0},
'SelectionGradientAmplitude': {'index': 5, 'VR': 'DS', 'VM': 1, 'value': 0.0},
'GradientDelayTime': {'index': 6,
'VR': 'DS',
'VM': 3,
'value': [36.0, 35.0, 31.0]},
'RfWatchdogMask': {'index': 7, 'VR': 'IS', 'VM': 1, 'value': 0},
'RfPowerErrorIndicator': {'index': 8, 'VR': 'DS', 'VM': 1, 'value': None},
'SarWholeBody': {'index': 9, 'VR': 'DS', 'VM': 3, 'value': None},
'Sed': {'index': 10,
'VR': 'DS',
'VM': 3,
'value': [1000000.0, 324.74800987, 324.74800832]}
...
}CSA headers often contain the complete scanner protocol in ASCCONV format under the MrPhoenixProtocol tag. This is automatically parsed into a nested dictionary:
>>> parsed_csa = CsaHeader(raw_csa).read()
>>> protocol = parsed_csa.get('MrPhoenixProtocol')
>>> if protocol:
... # Access protocol parameters
... tr = protocol['alTR'][0] # Repetition time
... te = protocol['alTE'][0] # Echo time
... print(f"TR: {tr} ms, TE: {te} ms")
TR: 2000 ms, TE: 30 msExtract diffusion-specific parameters for DTI/DWI analysis:
>>> # From image header (0x0029, 0x1020)
>>> image_header = CsaHeader(dcm[0x0029, 0x1020].value).read()
>>> b_value = image_header.get('B_value')
>>> gradient = image_header.get('DiffusionGradientDirection')
>>> print(f"B-value: {b_value}, Gradient: {gradient}")
B-value: 1000, Gradient: [0.707, 0.707, 0.0]Extract slice timing for slice timing correction:
>>> # From series header (0x0029, 0x1010)
>>> series_header = CsaHeader(dcm[0x0029, 0x1010].value).read()
>>> slice_times = series_header.get('MosaicRefAcqTimes')
>>> n_slices = series_header.get('NumberOfImagesInMosaic')
>>> print(f"Slice times: {slice_times[:3]}... ({n_slices} slices)")
Slice times: [0.0, 52.5, 105.0]... (64 slices)csa_header works seamlessly with NiBabel for comprehensive neuroimaging workflows:
import nibabel as nib
import pydicom
from csa_header import CsaHeader
# Load DICOM with both pydicom and NiBabel
dcm = pydicom.dcmread('scan.dcm')
nib_img = nib.load('scan.dcm')
# Extract CSA header information
if (0x0029, 0x1010) in dcm:
csa = CsaHeader(dcm[0x0029, 0x1010].value)
csa_info = csa.read()
# Use NiBabel for image data
data = nib_img.get_fdata()
# Use CSA for metadata
slice_times = csa_info.get('MosaicRefAcqTimes', [])
print(f"Image shape: {data.shape}")
print(f"Slice timing from CSA: {len(slice_times)} time points")- Slice Timing Correction: Extract
MosaicRefAcqTimesfor accurate fMRI preprocessing - Diffusion Imaging: Get b-values and gradient directions for DTI analysis
- Protocol Verification: Confirm acquisition parameters match expected values
- Quality Assurance: Extract technical parameters for QA pipelines
- BIDS Conversion: Generate complete metadata for BIDS-compliant datasets
See examples/nibabel_integration.py for complete integration examples.
The examples/ directory contains comprehensive usage examples:
-
basic_usage_example.py: Beginner-friendly introduction using example data
- Automatic download of example DICOM files
- Basic CSA header parsing
- Accessing specific CSA tags
- Perfect for first-time users!
-
nibabel_integration.py: Complete workflow combining csa_header with NiBabel
- Extract DWI parameters (b-values, gradients)
- Extract fMRI parameters (slice timing, TR/TE)
- Parse ASCCONV protocol parameters
- Batch processing multiple DICOM files
Run examples:
# Basic example with automatic data download
python examples/basic_usage_example.py
# NiBabel integration with your own DICOM
python examples/nibabel_integration.py path/to/siemens_dicom.dcmThis package uses hatch to manage development and packaging. To run the tests, simply run:
hatch run test
To run the tests with coverage, run:
hatch run cov
Or, to automatically generate an HTML report and open it in your default browser:
hatch run cov-show
Contributions are welcome! This project is community-maintained and aims to be a reliable tool for the medical imaging community.
- Report Issues: Found a bug or have a feature request? Open an issue
- Submit Pull Requests: See CONTRIBUTING.md for detailed guidelines
- Improve Documentation: Help make the docs better
- Share Examples: Contribute integration examples or use cases
# Clone the repository
git clone https://github.com/open-dicom/csa_header.git
cd csa_header
# Install hatch
pip install hatch
# Run tests
hatch run test:test
# Run linting
hatch run lint:all
# Install pre-commit hooks
hatch run pre-commit installSee CONTRIBUTING.md for complete development guidelines including:
- Code style requirements
- Testing requirements (90%+ coverage)
- Commit message conventions
- Pull request process
If you use csa_header in your research, please cite it using the following:
BibTeX:
@software{baratz_2025_csa_header,
author = {Baratz, Zvi and Brett, Matthew},
title = {csa_header: Parse CSA header information from Siemens MRI acquisitions},
year = 2025,
publisher = {Zenodo},
version = {v1.0.2},
doi = {10.5281/zenodo.17474448},
url = {https://doi.org/10.5281/zenodo.17474448}
}APA:
Baratz, Z., & Brett, M. (2025). csa_header: Parse CSA header information from Siemens MRI acquisitions (v1.0.2). Zenodo. https://doi.org/10.5281/zenodo.17474448
For the specific version you're using, please check the Zenodo record for the appropriate DOI and citation information.
Alternatively, you can use the CITATION.cff file in this repository, which is automatically recognized by GitHub and can be imported into reference managers.
csa_header is distributed under the terms of the MIT license.