The Data Access API (SoLDMDataAccess( C++ | Java | .NET ) ) provides methods to conveniently extract data from a volume managed by VolumeViz LDM. Data access can be used to extract data for computation, for segmentation or for display using other primitives. The data is accessible whether the SoVolumeData( C++ | Java | .NET ) node is part of a scene graph or not. The API allows an application to get the data associated with a specific tile at a specific resolution level. But more importantly it allows an application to ignore tiling and request the data values in a trace, a slice or an arbitrary subvolume. VolumeViz LDM takes care of copying data from all the required tiles to form the requested block of data.
VolumeViz LDM has changed the rules for visualization of very large volume data sets. It’s no longer necessary to have, and schedule time on, a cluster in order to do visualization of large data sets. Using LDM, multiple users can access a large data set simultaneously and work with it on their desktop or even laptop machines. This has made 3D visualization of large volumes feasible for a vastly larger group of both users and application developers. Seeing the success of VolumeViz LDM for visualization has greatly increased the interest in integrating LDM formatted data into other parts of the workflow. For example, storing computed data directly into LDM format could reduce total disk storage and make the data available for visualization much more quickly. Being able to compute and immediately visualize a subset of the data could increase productivity by allowing more iterations in the same amount of time.
SoLDMDataAccess( C++ | Java | .NET ) provides the following data requests:
Subvolume: The set of voxels inside a specified subvolume.
Trace: A column of axis aligned voxels (e.g. a seismic trace).
Line: The set of voxels intersecting an arbitrary line.
Polyline: The set of voxels intersecting an arbitrary polyline.
Plane: The set of voxels intersecting an arbitrary plane.
Tile: Direct access to the tile containing a specified voxel.
There is no data request method that returns a single voxel. However this request can be implemented using subvolume request or the tile request and is discussed in those subsections.
If possible, the Data Access API returns data from tiles resident in the system memory cache. If necessary, the Data Access API will automatically load any additional tiles required to satisfy the request. Loading additional tiles uses the volume’s associated volume reader object and multiple loader threads (if the reader is thread-safe).
The Data Access API can return data at any resolution level, independent of the resolution level currently being used for rendering. In most cases the application will request full resolution data for computation (resolution parameter = 0). Note that this might require loading some tiles that are not currently in memory, depending on which tiles are currently being used for rendering. The resolution parameter starts at zero for full resolution data and increases for each lower resolution version of the data. Effectively the resolution reduction is one over 2 to the resolution power. For example, resolution level 1 means the data is reduced by 1/2 (1 over 2 to the first power). The maximum value for resolution depends on the dimensions of the volume.
The Data Access API returns the data in an SoBufferObject( C++ | Java | .NET ) (specifically a subclass of SoBufferObject( C++ | Java | .NET )) created by the application. This is a data container that can be specialized to store data in CPU, OpenGL, CUDA or OpenCL memory. SoBufferObject( C++ | Java | .NET ) is part of the Open Inventor computing framework discussed in the chapter Chapter 24, Open Inventor Computing framework of the Mentor and summarized in the section computing framework of this chapter. The application is responsible for allocating (and freeing) the memory to store the requested data. For convenience, a first call to the appropriate API will return the size of the memory to be allocated. Once the buffer is allocated, a second call will extract the data from the volume.
All the data requests are specified in IJK (voxel) coordinates. This is true even though the data types used for requesting line and plane data (SbLine( C++ | Java ) and SbPlane( C++ | Java )) contain floating point values. SoLDMDataAccess( C++ | Java | .NET ) includes utility methods to convert a coordinate from XYZ to IJK and from IJK to XYZ. We will discuss how to convert line and plane definitions in section Get subvolume. For these requests the application can also specify a subvolume (e.g. region of interest) that limits the extent of the data request.
Each data request returns an “info” struct specific to the type of request. For every request the info struct contains an error code indicating whether the request succeeded, the size of the required buffer (in bytes) and the dimensions of the required buffer (in units of the volume’s data type). The data inside the returned buffer will be aligned as in the original volume. The info struct for some requests contains additional information such as the coordinates (for line, polyline and plane requests) or the tile id (for tile requests).
Each data request can be either synchronous or asynchronous. Synchronous means that all the data will be loaded before the function returns. Asynchronous means that the function returns immediately and the application is notified when the data is actually available. This allows the application to continue working while data is being loaded, for example to overlap data loading and computation without explicitly using multiple threads. The synchronous requests are named “getData” and the asynchronous requests are named “requestData”. The mechanics of specifying and interpreting each request are independent of whether the request is synchronous or asynchronous.
Access Mode
Three different modes are available for the data access API, providing control over whether the data is always loaded by tile, always loaded by request or loading tiles is deferred. This property can be specified using the method setGetDataMode(), for example:
CACHE: When data is requested, the data is copied from the LDM cache (tiles in memory) if possible. If some required tiles are not in the LDM cache, LDM will load those tiles into cache, then copy the data from the cache. This is the default behavior.
DIRECT: When data is requested, the data is copied from the LDM cache (tiles in memory) if possible. If some required tiles are not in the LDM cache, LDM will request the data directly from the volume reader without loading any tiles into the LDM cache memory. This could potentially be slower than the previous mode, but uses less I/O and less memory. It allows getting data without loading the whole tile into memory, for example when the requested data is a slice.
DIRECT_AND_PREFETCH: This mode is a mix of the previous modes. When data is requested, the data is copied from the LDM cache if possible. If some required tiles are not in the LDM cache, LDM will request the data directly from the volume reader to avoid reading complete tiles immediately, but will also schedule the relevant tiles to be loaded into the LDM cache memory asynchronously. This may improve performance overall if the application is likely to load additional data from these tiles.