# NiBabel

### Access a cacophony of neuro-imaging file formats

# Siemens format DICOM with CSA header

Recent Siemens DICOM images have useful information stored in a private header. We’ll call this the CSA header.

## CSA header

See this Siemens Syngo DICOM conformance statement, and a GDCM Siemens header dump.

The CSA header is stored in DICOM private tags. In the images we are looking at, there are several relevant tags:

    (0029, 1008) [CSA Image Header Type]             OB: 'IMAGE NUM 4 '
    (0029, 1009) [CSA Image Header Version]          OB: '20100114'
    (0029, 1010) [CSA Image Header Info]             OB: Array of 11560 bytes
    (0029, 1018) [CSA Series Header Type]            OB: 'MR'
    (0029, 1019) [CSA Series Header Version]         OB: '20100114'
    (0029, 1020) [CSA Series Header Info]            OB: Array of 80248 bytes

In our case we want to read the ‘CSAImageHeaderInfo’.

From the SPM (SPM8) code `spm_dicom_headers.m`

The CSAImageHeaderInfo and the CSA Series Header Info fields are of the same format. The fields can be of two types, CSA1 and CSA2.

Both are always little-endian, whatever the machine endian is.

The CSA2 format begins with the string ‘SV10’, the CSA1 format does not.

The code below keeps track of the position within the CSA header stream. We’ll call this `csa_position`. At this point (after reading the 8 bytes of the header), `csa_position == 8`. There’s a variable that sets the last byte position in the file that is sensibly still CSA header, and we’ll call that `csa_max_pos`.

## CSA1

### Start header

1. n_tags, uint32, number of tags. Number of tags should apparently be between 1 and 128. If this is not true we just abort and move to `csa_max_pos`.

2. unused, uint32, apparently has value 77

### Each tag

1. name : S64, null terminated string 64 bytes

2. vm : int32

3. vr : S4, first 3 characters only

4. syngodt : int32

5. nitems : int32

6. xx : int32 - apparently either 77 or 205

`nitems` gives the number of items in the tag. The items follow directly after the tag.

### Each item

1. xx : int32 * 4 . The first of these seems to be the length of the item in bytes, modified as below.

At this point SPM does a check, by calculating the length of this item `item_len` with `xx[0]` - the `nitems` of the first read tag. If `item_len` is less than 0 or greater than `csa_max_pos-csa_position` (the remaining number of bytes to read in the whole header) then we break from the item reading loop, setting the value below to ‘’.

Then we calculate `item_len` rounded up to the nearest 4 byte boundary tp get `next_item_pos`.

2. value : uint8, `item_len`.

We set the stream position to `next_item_pos`.

## CSA2

### Start header

1. hdr_id : S4 == ‘SV10’

2. unused1 : uint8, 4

3. n_tags, uint32, number of tags. Number of tags should apparently be between 1 and 128. If this is not true we just abort and move to `csa_max_pos`.

4. unused2, uint32, apparently has value 77

### Each tag

1. name : S64, null terminated string 64 bytes

2. vm : int32

3. vr : S4, first 3 characters only

4. syngodt : int32

5. nitems : int32

6. xx : int32 - apparently either 77 or 205

`nitems` gives the number of items in the tag. The items follow directly after the tag.

### Each item

1. xx : int32 * 4 . The first of these seems to be the length of the item in bytes, modified as below.

Now there’s a different length check from CSA1. `item_len` is given just by `xx[1]`. If `item_len` > `csa_max_pos - csa_position` (the remaining bytes in the header), then we just read the remaining bytes in the header (as above) into `value` below, as uint8, move the filepointer to the next 4 byte boundary, and give up reading.

2. value : uint8, `item_len`.

We set the stream position to the next 4 byte boundary.