Loading RAW Files

<< Click to Display Table of Contents >>

Navigation:  XStream® HDVR® SDK > Implementation Concepts > Data Loading Fundamentals >

Loading RAW Files

Previous pageReturn to chapter overviewNext page

C++ C++ Java Java .NET .NET

Summary

 

The XStream® HDVR® SDK supports the loading of RAW datasets, datasets that consist of binary volume data only, without headers or other metadata. A RAW dataset can be contained in either a single file or in multiple files. RAW data can be loaded either synchronously or asynchronously.

 

Loading RAW Data

 

When using the C++ API, loading of RAW datasets is accomplished with the IServerContext::LoadRawFiles() method. This method takes as an input parameter a pointer to a RAW_DATASET_DESCRIPTION structure that describes the properties of the RAW files to be loaded. The function returns as an output parameter an IVolumeDataContext object representing the loaded dataset.

 

When using the JAVA/.NET APIs, loading of RAW datasets is accomplished with the hdrcServerContext.loadRawFiles() method. This method takes as an input parameter a pointer to a RAW_DATASET_DESCRIPTION structure that describes the properties of the RAW files to be loaded. The function returns as an output parameter a hdrcVolumeDataContext object representing the loaded dataset.

 

A RAW_DATASET_DESCRIPTION structure specifies the properties of a RAW dataset, and is used as an input parameter to the IServerContext::LoadRawFiles() method. Its fields specify the following parameters.

 

VECTOR3L RAW_DATASET_DESCRIPTION::Dimension

 

This member stores in pixels the X and Y dimensions of each slice in the dataset. Each slice must be a square: X must equal Y. The HDVR SDK does not support datasets in which X does not equal Y. The Z parameter stores the number of slices in the dataset. Note that each RAW file may have multiple slices.

 

RAW_FILE_DATA_DESCRIPTION *RAW_DATASET_DESCRIPTION::Files

 

This member is an array of RAW_FILE_DATA_DESCRIPTION structures specifying the properties of each file in the dataset. There must be one array entry per file. See the description of RAW_FILE_DATA_DESCRIPTION below for more information on this parameter.

 

int RAW_DATASET_DESCRIPTION::NumFiles

 

This member stores the number of files in the dataset. It is also the number of entries in the RAW_DATASET_DESCRIPTION::Files array. There should be one RAW_FILE_DATA_DESCRIPTION object for each file.

 

MATRIX44D RAW_DATASET_DESCRIPTION::Orientation

 

This matrix specifies a transformation to be applied to the dataset. The matrix is propagated to the IVolumeDataContext::VOLUME_DATA_PARAMS structure after the dataset is loaded.

 

VECTOR3D RAW_DATASET_DESCRIPTION::Spacing

 

This member describes the spacing in millimeters between pixels in the X and Y coordinates, and the spacing between slices in Z.

 

The RAW_FILE_DATA_DESCRIPTION Structure

 

One of the input parameters to the IServerContext::LoadRawFiles() method is an array of RAW_FILE_DATA_DESCRIPTION structures that is used to specify the properties of each of the files comprising a RAW dataset. One structure should be defined per file, with fields that specify the following parameters.

 

boolean RAW_FILE_DATA_DESCRIPTION::BigEndian

 

TRUE if the most significant bytes come last in each data sample, FALSE otherwise.

 

ENUM_FILE_DATA_TYPE RAW_FILE_DATA_DESCRIPTION::DataType

 

This specifies the type of data in the RAW file. It is a member of the ENUM_FILE_DATA_TYPE enumeration. Either ENUM_FILE_DATA_TYPE::FDT_INTEGER or ENUM_FILE_DATA_TYPE::FDT_FLOAT.

 

char *RAW_FILE_DATA_DESCRIPTION::FileName

String RAW_FILE_DATA_DESCRIPTION::FileName

 

This defines the path and file name of the file to be loaded.

 

int RAW_FILE_DATA_DESCRIPTION::LinePitch

 

This specifies the size in bytes of each line of data in a scan slice. This is also known as stride. If each data point in the file has a two-byte value, and the dimensions of the slice are 512 x 512, then the pitch is 2 * 512 = 1024. ENUM_FILE_DATA_TYPE::LinePitch can be negative. A negative pitch would be used when the data in each slice is recorded in a bottom up rather than top down format.

 

double RAW_FILE_DATA_DESCRIPTION::MinValue

double RAW_FILE_DATA_DESCRIPTION::MaxValue

 

These members specify a range of values in the dataset that map to the internally represented range of 0 to 32768. For example, if the dataset contains floating point values from -1 to 1, then ENUM_FILE_DATA_TYPE::MinValue would be set to -1 and ENUM_FILE_DATA_TYPE::MaxValue would be set to +1. At load time, the data values in the file would then map to the 0 to 32768 range.

 

int RAW_FILE_DATA_DESCRIPTION::NumBits

 

For integers, this member should be set to 8, 16 or 32. For floating point values, it should be set to 32 or 64.

 

int RAW_FILE_DATA_DESCRIPTION::NumSlices

 

This specifies the number of data slices in the file.

 

int RAW_FILE_DATA_DESCRIPTION::Offset

 

This describes the number of bytes from the beginning of the file to the beginning of the first slice. This member is used to skip over any header data in the file.

 

boolean RAW_FILE_DATA_DESCRIPTION::Signed

 

This member is only used with integer data, and should be set to TRUE or FALSE to designate if the RAW file contains signed data.

 

int RAW_FILE_DATA_DESCRIPTION::SlicePitch

 

This member is used if an individual file contains more than one slice. It specifies the number of bytes between slices. ENUM_FILE_DATA_TYPE::SlicePitch can be negative. A negative slice pitch would be used when the slices in the file are stored in order from inferior to posterior (bottom to top).

 

RAW_DATASET_DESCRIPTION datasetDesc;

BCOM_ZEROMEMORY( datasetDesc );

 

datasetDesc.Dimension.x = 512;

datasetDesc.Dimension.y = 512;

datasetDesc.Dimension.z = 1; 

datasetDesc.NumFiles = 1;

datasetDesc.Orientation.setIdentity();

datasetDesc.Spacing.x = 1;

datasetDesc.Spacing.y = 1;

datasetDesc.Spacing.z = 1;

datasetDesc.Files = new RAW_FILE_DATA_DESCRIPTION[datasetDesc.NumFiles];

for( int i = 0; i < datasetDesc.NumFiles; i++ ) {

   datasetDesc.Files[i].BigEndian = H_TRUE;

   datasetDesc.Files[i].DataType = FDT_INTEGER;

   char *fileName = "C:/Datasets/RAW/fileN.raw";

   datasetDesc.Files[i].FileName = fileName;

   datasetDesc.Files[i].NumBits = 32;

   datasetDesc.Files[i].LinePitch = datasetDesc.Files[0].NumBits * datasetDesc.Dimension.x;

   datasetDesc.Files[i].MinValue = 1000;

   datasetDesc.Files[i].MaxValue = 2000;

   datasetDesc.Files[i].NumSlices = 1;

   datasetDesc.Files[i].Offset = 0;

   datasetDesc.Files[i].Signed = H_FALSE;

   datasetDesc.Files[i].SlicePitch = datasetDesc.Files[0].LinePitch * datasetDesc.Dimension.y;

}

 

pServerContext->LoadRawFiles(&pVolumeData, &datasetDesc);

 

RAW_DATASET_DESCRIPTION datasetDesc = new RAW_DATASET_DESCRIPTION();

 

datasetDesc.Dimension.x = 512;

datasetDesc.Dimension.y = 512;

datasetDesc.Dimension.z = 1; 

datasetDesc.NumFiles = 1;

datasetDesc.Orientation.setIdentity();

datasetDesc.Spacing.x = 1;

datasetDesc.Spacing.y = 1;

datasetDesc.Spacing.z = 1;

datasetDesc.Files = new RAW_FILE_DATA_DESCRIPTION[datasetDesc.NumFiles];

for( int i = 0; i < datasetDesc.NumFiles; i++ ) {

   datasetDesc.Files[i].BigEndian = TRUE;

   datasetDesc.Files[i].DataType = RAW_DATASET_DESCRIPTION.FDT_INTEGER;

   datasetDesc.Files[i].FileName = "C:/Datasets/RAW/fileN.raw";

   datasetDesc.Files[i].NumBits = 32;

   datasetDesc.Files[i].LinePitch = datasetDesc.Files[0].NumBits * datasetDesc.Dimension.x;

   datasetDesc.Files[i].MinValue = 1000;

   datasetDesc.Files[i].MaxValue = 2000;

   datasetDesc.Files[i].NumSlices = 1;

   datasetDesc.Files[i].Offset = 0;

   datasetDesc.Files[i].Signed = FALSE;

   datasetDesc.Files[i].SlicePitch = datasetDesc.Files[0].LinePitch * datasetDesc.Dimension.y;

}

serverContext.loadRawFiles(volumeData, datasetDesc);

 

RAW_DATASET_DESCRIPTION datasetDesc = new RAW_DATASET_DESCRIPTION();

 

datasetDesc.Dimension.x = 512;

datasetDesc.Dimension.y = 512;

datasetDesc.Dimension.z = 1; 

datasetDesc.NumFiles = 1;

datasetDesc.Orientation.setIdentity();

datasetDesc.Spacing.x = 1;

datasetDesc.Spacing.y = 1;

datasetDesc.Spacing.z = 1;

datasetDesc.Files = new RAW_FILE_DATA_DESCRIPTION[datasetDesc.NumFiles];

for( int i = 0; i < datasetDesc.NumFiles; i++ ) {

   datasetDesc.Files[i].BigEndian = TRUE;

   datasetDesc.Files[i].DataType = RAW_DATASET_DESCRIPTION.FDT_INTEGER;

   datasetDesc.Files[i].FileName = "C:/Datasets/RAW/fileN.raw";

   datasetDesc.Files[i].NumBits = 32;

   datasetDesc.Files[i].LinePitch = datasetDesc.Files[0].NumBits * datasetDesc.Dimension.x;

   datasetDesc.Files[i].MinValue = 1000;

   datasetDesc.Files[i].MaxValue = 2000;

   datasetDesc.Files[i].NumSlices = 1;

   datasetDesc.Files[i].Offset = 0;

   datasetDesc.Files[i].Signed = FALSE;

   datasetDesc.Files[i].SlicePitch = datasetDesc.Files[0].LinePitch * datasetDesc.Dimension.y;

serverContext.loadRawFiles(volumeData, datasetDesc);

 

 

Asynchronous Dataset Loading

 

The C++ API IServerContext::LoadRawFiles() method is a synchronous blocking method. It will not return until the RAW dataset has been loaded. Loading a dataset can take a significant amount of time, and it may not be optimal to have the application block while the dataset is being loaded. Additionally, display of a progress bar or other user interface data may be useful while dataset loading is in process. For these reasons, an asynchronous loading method is provided. Asynchronous dataset loading is accomplished with the IServerContext::StartJobLoadRawFiles(), IServerContext::GetJobInfo(), and IServerContext::FinishJobLoadRawFiles() methods.

 

The IServerContext::StartJobLoadRawFiles() method begins the dataset loading process. This method takes two parameters. The first parameter is a pointer to an integer used to store the job ID associated with the loading process. This will be returned as an output parameter when the IServerContext::StartJobLoadRawFiles() method returns. The second parameter is the address of a RAW_DATASET_DESCRIPTION structure. Use of the RAW_DATASET_DESCRIPTION structure is described in the Loading RAW Data section above.

 

The IServerContext::GetJobInfo() method is used to return information on the progress and status of the loading operation. This method takes as an input parameter the jobID value returned from the IServerContext::StartJobLoadRawFiles() method, used to identify the asynchronous loading operation. The IServerContext::GetJobInfo() method returns as an output parameter a pointer to a JOBINFO structure. The JOBINFO::jobprog value stores the job progress. This value will be 0 to 100, representing percentage of job completion, with a value of 100 indicating completion of the job. The JOBINFO::jobret value stores the return value from the loading operation when it has completed.

 

The IServerContext::FinishJobLoadRawFiles() method is used to finalize the loading process. This method takes two parameters. The first is the address of an IVolumeDataContext pointer set to the address of the IVolumeDataContext object that represents the loaded volume data. The second parameter is the job ID for the desired asynchronous loading operation returned by the IServerContext::StartJobLoadRawFiles() method. Note that the IServerContext::FinishJobLoadRawFiles() method will block until the server side loading function completes.

 

h_int64 jobID;

 

// Start the asynchronous loading operation.

pServerContext->StartJobLoadRawFiles(&jobID, &datasetDesc);

 

JOBINFO jobInfo;

while(jobInfo.jobprog < 100) {

   // Get loading progress

   pServerContext->GetJobInfo(jobID, &jobInfo);

 

// Loading process is complete

IVolumeDataContext *pVolumeData = NULL;

pServerContext->FinishJobLoadRawFiles(&pVolumeData, jobID);

 

The Java/.NET API hdrcServerContext.loadRawFiles() method is a synchronous blocking method. It will not return until the RAW dataset has been loaded. Loading a dataset can take a significant amount of time, and it may not be optimal to have the application block while the dataset is being loaded. Additionally, display of a progress bar or other user interface data may be useful while dataset loading is in process. For these reasons, an asynchronous loading method is provided. Asynchronous dataset loading is accomplished with the hdrcServerContext.startJobLoadRawFiles(), hdrcServerContext.getJobInfo(), and hdrcServerContext.finishJobLoadRawFiles() methods.

 

The hdrcServerContext.startJobLoadRawFiles() method begins the dataset loading process. This method takes a reference to a RAW_DATASET_DESCRIPTION structure that defines the RAW dataset to load. Use of the RAW_DATASET_DESCRIPTION structure is described in the Loading RAW Data section above. The hdrcServerContext.startJobLoadRawFiles() method returns an integer that represents the job ID associated with the asynchronous loading process.

 

The hdrcServerContext.getJobInfo() method is used to return information on the progress and status of the loading operation. This method takes as an input parameter the jobID value returned from the hdrcServerContext.startJobLoadRawFiles() method which is used to identify the asynchronous loading operation. The hdrcServerContext.getJobInfo() method returns a reference to a hdrcJobInfo structure. The hdrcJobInfo.m_prog value stores the job progress. This value will be 0 to 100, representing percentage of job completion, with a value of 100 indicating completion of the job. The hdrcJobInfo.m_err value stores the return value from the loading operation when it has completed.

 

The hdrcServerContext.finishJobLoadRawFiles() method is used to finalize the loading process. This method takes as an input parameter the job ID for the desired asynchronous loading operation returned by the hdrcServerContext.startJobLoadRawFiles() method. The hdrcServerContext.finishJobLoadRawFiles() method returns a reference to a hdrcVolumeDataContext object that represents the loaded volume data. Note that the hdrcServerContext.finishJobLoadRawFiles() method will block until the server side loading function completes.

 

// Start the asynchronous loading operation.

long jobID = serverContext.startJobLoadRawFiles(datasetDesc);

 

hdrcJobInfo jobInfo;

while(jobInfo.m_prog < 100) {

   // Get loading progress

   jobInfo = serverContext.getJobInfo(jobID);

 

// Loading process is complete

hdrcVolumeDataContext volumeData;

volumeData = serverContext.finishJobLoadRawFiles(jobID);