# Binary Data Resources

## Overview

The XCEDE 2 Binary Data Resource component is used to provide a generic interface to a binary data stream stored in one or more external files. Any of the binary data resource types described in this chapter can be used anywhere an abstract_resource_t is called for (with the appropriate `xsi:type` attribute); in the current XCEDE schema, these locations are the top-level `<resource>` element and the `<dataResource>` child element of `<acquisition>`.

XCEDE provides multiple layers of derived types to store more specialized information about the binary data. The base type and each of the derived types are described in turn.

abstract_resource_t

The abstract base type abstract_resource_t provides a few elements and attributes that are especially important for binary data resources. In particular, the `<uri>` element and its `offset` and `size` attributes point to a chunk of data stored in an external file. A series of `<uri>` elements define a stream of data that may be described in greater detail by the data types described below.

binaryDataResource_t

This type derives from abstract_resource_t and allows an application to interpret the data stream as a sequence of data items with a given data type (`<elementType>`) and byte order (`<byteOrder>`).

dimensionedBinaryDataResource_t

The data stream, until now, could only be interpreted as a one-dimensional sequence. This type provides `<dimension>` elements that allow the data stream to be interpreted as a multi-dimensional array of data items. Each dimension has a `<size>` and a `<label>`, as well as the ability to discard subsets of the data in the data stream (using the `outputSelect` attribute).

mappedBinaryDataResource_t

This type places the multi-dimensional array of data items represented by dimensionedBinaryDataResource_t into an arbitrary coordinate system.

## Examples

Several examples of binary data are presented here, each showing the use of one of the different binary data types described in this chapter.

### Basic data stream

The basic binary data resource type describes a sequence of data items. For example, consider a data file (`random_data_file.bin`) containing 2048 random 32-bit floating point numbers, stored in little-endian (least-significant-byte first) order. The `<dataResource>` describing this data is shown in .

Simple binaryDataResource_t example

Note the `xsi:type` specifying that this `<resource>` element is of type binaryDataResource_t. (The `xsi:` prefix should have already been declared previously in the XML file using something similar to `xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"`)

The `<elementType>` element is restricted to one of several pre-defined strings (see the schema for details). The `<byteOrder>` element must be `lsbfirst` for little-endian data or `msbfirst` for big-endian data.

If the `<compression>` element is specified, it specifies that the file(s) pointed to by the `<uri>` elements are compressed. The content of the element should specify which type of compression (the only compression method specifically recognized by this specification is `gzip`). The `size` and `offset` attributes in the `<uri>` element always refer to the uncompressed data. An example of this is shown in .

binaryDataResource_t with compression

As a special case, if the application does not find the file pointed to by a URI, and the `<compression>` element is not present, it may search for the same file with an appended `.gz` suffix, and if it exists, treat it as implicitly gzip-compressed data. shows how the same data in could be expressed using this alternative method. Pointing to the uncompressed version of the file (even when only the compressed version exists) allows the user to decompress or compress the data file at will, without affecting the ability of the application to read the data using the same binaryDataResource_t. Note that the `<uri>` and `<compression>` elements must be internally consistent. It would be an error to reference the uncompressed file `random_data_file.bin` and yet say that it was compressed using `<compression>gzip</compression>`. Likewise, explicit references to the compressed file (especially files that do not have the `.gz` suffix) must specify the compression method explicitly using the `compression` element.

binaryDataResource_t with implicit compression

### Dimensioned data

Consider a camera that acquires an image using a 256x256 matrix of big-endian 32-bit signed integer voxels. This data has two spatial dimensions, which, by convention, we label x, and y (and z if a third spatial dimension is needed, and t if there is a time dimension). shows how this data might be represented.

dimensionedBinaryDataResource_t example

Dimensions are ordered from fastest-moving to slowest-moving. So in the above example, the x dimension index changes on each consecutive data item, but the y dimension changes every 256 elements.

### Mapped data

A mapped binary data resource is a (perhaps multidimensional) array of values, the matrix indices of which can be converted into a location in a given coordinate system. The location of the bounding box of the data in this space is given by specifying a location (in target-space coordinates) for the the first data item, and two things for each dimension: a unit-length direction vector (in the target-space coordinate system) and the spacing between successive data items in that dimension. The transformation matrix for a three-dimensional coordinate system has the form shown in . This transformation matrix converts from matrix indices `(x,y,z)` to a coordinate location `(a,b,c)`. shows how the components of a transformation of MR image data into scanner RAS (Right/Anterior/Superior) coordinates are represented in a mappedBinaryDataResource_t. The unit vectors for each dimension are (XA XB XC) = (1 0 0), (YA YB YC) = ( 0 1 0 ), and (ZA ZB ZC) = ( 0 0 1 ), and are placed in the `<direction>` elements in each `<dimension>` element. The spacing values (SX SY SZ) = ( 3.75mm 3.75mm 4mm ) are put in the `<spacing>` element in each `<dimension>`. The coordinates of the first voxel in the data are given by (OA OB OC) = ( -120 -120 -52 ).

Transformation matrix

mappedBinaryDataResource_t example

### Advanced topic: split dimensions and outputSelect

A more complicated example is given by data generated by a Siemens MR scanner. In this case, the data represents a three-dimensional 64x64x32 image, stored in DICOM format. However, because the earlier versions of the DICOM format did not support three-dimensional data in one file, Siemens came upon the clever idea to tile the 32 two-dimensional slices across an NxN two-dimensional grid ().

A tiledimage

Applications may naturally want to express this data as a three-dimensional block, with columns, rows, and slices. In a conventionally-stored three-dimensional X×Y×Z image, the first X voxels compose the first row in the first slice, and then the next X voxels are the second row in the first slice; likewise the first X*Y voxels are the first slice, and the next X*Y voxels are the second slice, and so on. However, in the tiled image, though the first X voxels are again the first row in the first slice, the next X voxels are the first row in the second slice! At first it would seem that the dimension order has merely been switched, and specifying the labels of the dimensions as x, z, and y would fix things. However, we only hit six slices' first rows before hitting going to the second row of the same six slices. Only after going through all the rows in this fashion in the first six slices do we go on to the next six slices.

The end result is that the dimension that we are calling the z dimension has been split in two. The two components of the z dimension are interleaved with the x and y dimensions like so: x, z1, y, z2. The two components of the z dimension are distinguished with the `splitRank` attribute, as shown in .

Split dimension example

Applications should read this data as if it were four dimensions, and then permute the data to bring the two z dimensions together (in the order specified by splitRank) in the position of the highest-ranked split dimension, and the two dimensions can then be merged into one. The size of the new z dimension is the product of the sizes of the component split dimensions, so 6 * 6 = 36.

You may recall that the original data was acquired as a 64x64x32 volume, but the NxN tiling representation requires that the number of tiles be the square of an integer N. One more mechanism has been added to the `<dimension>` element to accomodate the presence of data that should be disregarded: the `outputSelect` attribute (see ).

`outputSelect` example

The `outputSelect` attribute specifies a list of indices along the given dimension (or combined dimension if it occurs on the highest-ranked component of a split dimension) that should be regarded as valid data. Data in the other indices should be ignored.