Data Tables Technical Guide
Section 5 - RETRIEVING DATA TABLE DATA WITH THE SEDRIS API
5.1 Overview

The SEDRIS API and its use is documented in the following volumes of Part 4 of the Documentation Set:

  • Volume 13: How to Extract Data from SEDRIS Transmittals

  • Volume 14: How to Produce SEDRIS Transmittals

  • Volume 17: API Reference Manual

In this section, the reader is assumed to be familiar with the SEDRIS API. This section provides supplemental information on SEDRIS API functions that are related to the extraction of data from <Data Table> instances.

5.2 Data Table Sub-Extents

The SEDRIS API provides one function to retrieve data from <Data Table> instances. The function SE_GetDataTableData() is used to retrieve data for the complete <Data Table> signature, or for a subset of the signature. This is important if the table is large and the data consumer is interested only in part of the table, or if the data consumer has memory constraints and can only handle the table piecemeal. <Data Table> cell subsets are specified using a SEDRIS API data type, SE_Data_Table_Sub_Extent.

SE_Data_Table_Sub_Extent contains 2 fields: axes_count and axes_bounds, where axes_count specifies the size of the axes_bounds array. When a handle to a SE_Data_Table_Sub_Extent, we'll call it extents_ptr, is provided to the data table retrieval function, the value of extents_ptr->axes_count is required to match the number of <Axis> components of the <Data Table> instance. Each entry in axes_bounds specifies the desired range of axis index values for the corresponding <Axis>. The indexing is zero-based, so that for the kth <Axis> component of the table for which cells are being retrieved, where axis_value_count is the number of tick marks on the kth <Axis>,

0 <= extents_ptr->axes_bounds[k].first_index <= extents_ptr->axes_bounds[k].last_index <= axis_value_count - 1

The number of cells, cell_count, specified by an SE_Data_Table_Sub_Extent is the product of the lengths of the index ranges for each axis.

cell_count = product of (1 + extents_ptr->axes_bounds[k].last_index - extents_ptr->axes_bounds[k].first_index)

for k = 0 to k = axes_count -1.

5.3 SE_GetDataTableData()

If the signature of a <Data Table> has more than one <Table Property Description> (signature item), the SE_GetDataTableData() function allows several or all signature elements to be retrieved in one function call. The prototype for SE_GetDataTableData() is:
SE_Return_Code SE_GetDataTableData
(
SE_Object data_table,
const SE_Data_Table_Sub_Extent * extents_ptr,
SE_Integer_Positive element_count,
const SE_Integer_Positive element_indices[],
SE_Store store_in,
SE_Data_Table_Data ** data_table_data_out_ptr
);

The data_table argument is an SE_Object representing a handle to the <Data Table> instance for which cell data is being retrieved. The extents_ptr argument uses the SE_Data_Table_Sub_Extent data type to specify the index bounds for the cells for which signature element data is desired.

Please see section 5.2 for more information about the extents_ptr argument.

The element_count specifies the number of elements to be returned per cell, and is the dimension of the element_indices array that follows. The element_indices array itself both indicates which elements are requested for each cell and specifies the order in which they shall be retrieved; in other words, the retrieval order is not restricted to the <Table Property Description> order. The <Table Property Description> indices used in the element_indices array are 1-based.

The store_in argument, in this <Data Table> retrieval function, is required in order to allow the API to manage the memory associated with the cells of the given <Data Table> instance, rather than requiring the user to do so. Consequently, the user does not allocate the memory within data_table_data_out_ptr, but merely provides a handle to the structure, which is then filled out by the API if valid parameters were passed in and all operations succeeded (e.g., memory allocation didn't fail).

As an example of the usage of SE_GetDataTableData(), consider the "Surface Backscatter" table from section 3.1, from which a consumer wishes to extract the value corresponding to the angle of incidence of 30 degrees from the IR band. The table is a 2-dimensional array, in which the first <Axis> represents the EM band ( EAC_EM_BAND ), wherein the IR band ( EEC_EMBAND_INFRARED ) is located at index 2 in the (zero-based) axis_value_array. On the second <Axis> ( EAC_INCIDENCE_ELEV_ANGLE_LOCAL ), the value 30 has index 1. Consequently, to specify a single cell, the index start and stop bounds on the first axis are from 2 to 2, and those on the second axis are from 1 to 1. In the following code example (Figure 5-1, the extents_ptr argument is set, then the value ( EAC_SURFACE_BACKSCATTER ) is retrieved.

      SE_Return_Code             return_code;
      SE_Data_Table_Data        *dtd_results;
      EDCS_Long_Float           *data_values;
      SE_Data_Table_Sub_Extent   dtd_extents;
      SE_Index_Range             ax_range[] = {{2, 2}, {1, 1}};
      SE_Integer_Positive        element_count = 1;
const SE_Integer_Positive        element_indices[] = { 1 };


/*
 * Set extents for cell (2, 1)
 */
extent.axes_count  = 2;
extent.axes_bounds = ax_range;

/*
 * back_scatter_table has already been retrieved
 * dtd_store has already been created by SE_CreateStore
 */
return_code = SE_GetDataTableData
              (
                back_scatter_table,
               &dtd_extents,
                element_count,
                element_indices,
                dtd_store,
               &dtd_results
         );

/*
 * Extract data value from dtd_result
 */
if ((return_code == SE_RET_CODE_SUCCESS) &&
    (dtd_results.value_type == SE_DTD_VT_SINGLE_FLOAT))
{
    int i = 0;
    data_values = dtd_results.dt_array.single_long_float_values;
    for(i = 0; i < dtd_results.data_count; i++)
    {
       printf("%f ", data_values[i]);
    }
    printf("\n");
}
Figure 5-1 Using SE_GetDataTableData() to get a single element

Retrieving the entire table, rather than one value, requires only changes to the values within the >extent structure, as shown in Figure 5-2, since store_in handles the memory management aspects of the retrieval for the user.

SE_Index_Range             ax_range[] = {{0, 0}, {4, 5}};
Figure 5-2 Setting Maximum Sub-Extents

The user is not required to possess a priori knowledge of the exact value count of each <Axis> component of a <Data Table> instance to fill in an SE_Data_Table_Sub_Extent structure, however. As a convenience, the Transmittal Access Level 1 API provides the SE_GetDataTableSubExtent() function, which allocates the axes_bounds field and sets each range entry with the minimum (0) and maximum ( axis_value_count - 1) index values. As an additional feature, the function also computes the cell count of the specified extent. This is illustrated in Figure 5-3, below.

...
SE_Data_Table_Sub_Extent  extent;
SE_Integer_Unsigned       cell_count;

/*
 * Get the complete extents
 */
status = SE_GetDataTableSubExtent
         (back_scatter_table, &extent, &cell_count);

...
/* code that uses extent would be located here */

SE_FreeDataTableSubExtent(&extent);
Figure 5-3 Using SE_GetDataTableSubExtent()

Note that the user calls SE_FreeDataTableSubExtent() to free the memory allocated within the SE_Data_Table_Sub_Extent structure when it is no longer needed.