Skip to content

AFNI and NIfTI Server for NIMH/NIH/PHS/DHHS/USA/Earth

Sections
Personal tools
You are here: Home » SSCC » rwcox's Home » AFNI Code Commentary » The THD_3dim_dataset struct (incomplete)

The THD_3dim_dataset struct (incomplete) The THD_3dim_dataset struct (incomplete)

Document Actions
Submitted by bpittman. on 2005-04-04 10:00.
This struct is the internal storage for the AFNI dataset.
This will be long, since there are several sub-structs to cover. I'll start with an overview of the top-level struct and work my way down down down.

Here is the typedef for the struct from 3ddata.h:

typedef struct THD_3dim_dataset {
  int type ;        /*!< type code */
  int view_type ;   /*!< view code */
  int func_type ;   /*!< one of the FUNC_*_TYPE or ANAT_*_TYPE codes */

  char label1[THD_MAX_LABEL] ;  /*!< No longer used */
  char label2[THD_MAX_LABEL] ;  /*!< No longer used */

  THD_datablock   * dblk ;      /*!< pointer to struct with actual data */
  THD_dataxes     * daxes ;     /*!< info about axes (where dataset is in space) */
  THD_dataxes     * wod_daxes ; /*!< warp-on-demand axes (for interpolated dataset) */
  int               wod_flag ;  /*!< if true, use wod_daxes, otherwise use daxes */
  THD_timeaxis    * taxis ;     /*!< non-NULL --> this is a 3D+t dataset */
  THD_marker_set  * markers ;   /*!< user set mark points (if non-NULL) */

  struct THD_3dim_dataset * warp_parent; /*!< non-NULL --> this dataset is warped from that */
  THD_warp                * warp ;       /*!< this is the coordinate-to-coordinate warp */
  THD_warp                * vox_warp ;   /*!< this is the index-to-index warp */

  struct THD_3dim_dataset * anat_parent; /*!< non-NULL --> linked to this as anatomical ref */

  THD_statistics          * stats ;      /*!< statistics about the sub-brick data */

  float stat_aux[MAX_STAT_AUX] ;         /*!< global auxiliary statistics info */

  char warp_parent_name[THD_MAX_NAME] ;  /*!< "name" of warp_parent dataset (no longer used) */
  char anat_parent_name[THD_MAX_NAME] ;  /*!< "name" of anat_parent dataset (no longer used) */
  char self_name[THD_MAX_NAME]        ;  /*!< my own "name" (no longer used) */

  int death_mark ;                 /*!< dataset is marked for destruction */

  MCW_idcode idcode ;              /*!< globally unique (I hope) ID code for this dataset */
  MCW_idcode anat_parent_idcode ;  /*!< ID code for warp_parent dataset */
  MCW_idcode warp_parent_idcode ;  /*!< ID code for anat_parent dataset */

  char * keywords ;           /*!< 30 Nov 1997: keyword list for dataset */

  THD_usertaglist * tagset ;  /*!< 23 Oct 1998: see plug_tag.c */

  KILL_list kl ;              /*!< Stuff to delete if this dataset is deleted (see killer.h) */
  XtPointer parent ;          /*!< Somebody that "owns" this dataset */

  THD_warp *self_warp ;       /*!< 26 Aug 2002: self warp (for w-o-d) */

  char *tcat_list ; /*!< 03 Aug 2004: list of filenames to cat together (THD_open_tcat) */
  int   tcat_num ;
  int  *tcat_len ;

} THD_3dim_dataset ;
Most of the entries are pointers to sub-structs, which will be discussed in turn later.

Dataset Types:
For a long time, there was a rigid distinction in the AFNI GUI between "anatomical" dataset and "functional" datasets. The former could be used as underlays and the latter as overlays. That distinction was erased in early 2004, but some of this old segregation lingers in the 3 "type codes" that start the dataset struct:

  • int type = one of the constants HEAD_ANAT_TYPE, HEAD_FUNC_TYPE, GEN_ANAT_TYPE, or GEN_FUNC_TYPE (0..3). Only HEAD_ANAT_TYPE datasets can have Talairach markers. The original thought was that non-brain datasets would use the "GEN_" codes, but this idea never developed.

  • int view_type = one of the constants VIEW_ORIGINAL_TYPE, VIEW_ACPCALIGNED_TYPE, or VIEW_TALAIRACH_TYPE (0..2). These correspond to the +orig, +acpc, and +tlrc filenames. The dataset input software will be mondo-unhappy if the view_type code and the filename don't match.

  • func_type = one of the FUNC_*_TYPE constants (0..11) or ANAT_*_TYPE constants (0..11). Unfortunately, these codes overlap; that is, you can't tell what type a dataset really is without examining type and int func_type. Most of these types are now obsolescent or worse. I recommend in the future that all datasets be created either as ANAT_BUCK_TYPE or FUNC_BUCK_TYPE (both have func_type=11).

THD_datablock *dblk = Where the data arrays are hidden
The actual data for the dataset is stored within this struct. The typedef is given below:

typedef struct {
  int type ;              /*!< type code: DATABLOCK_TYPE */
  int nvals ;             /*!< number of 3D bricks */

  MRI_IMARR * brick  ;    /*!< array of pointers to each 3D brick */
  float * brick_fac  ;    /*!< array of scale factors for subbricks */
  int *  brick_bytes ;    /*!< array of data size of each subbrick */

  char ** brick_lab  ;    /*!< labels for all subbricks                 */
  char ** brick_keywords; /*!< keywords strings for all subbricks       */
  int *   brick_statcode; /*!< a FUNC_*_TYPE ==> kind of statistic here */
  float **brick_stataux ; /*!< stat_aux parameters for each subbrick    */

  int64_t total_bytes ;   /*!< totality of data storage needed */
  int     malloc_type ;   /*!< memory allocation method */
  int     locked ;        /*!< Feb 1998: locked in memory (un-purgeable) */

  int    master_nvals ;   /*!< Number of nvals in master dataset */
  int *  master_ival ;    /*!< [i] = subbrick index in master of subbrick #i */
  int *  master_bytes ;   /*!< [i] = size of subbrick #i in master */

  float master_bot ;      /*!< range of data values to keep from master: bot */
  float master_top ;      /*!< range of data values to keep from master: top */

  THD_diskptr * diskptr ; /*!< where the data is on disk (if anywhere!) */

  int       natr ;        /*!< number of attributes read from disk */
  int       natr_alloc ;  /*!< number of attributes allocated in atr below */
  ATR_any * atr ;         /*!< array of attributes (from the header) */

  KILL_list kl ;          /*!< Stuff to delete if this struct is deleted */
  XtPointer parent ;      /*!< Somebody who "owns" me (the dataset) */

  char shm_idcode[32] ;   /*!< Idcode for shared memory buffer, if any */
  int  shm_idint ;        /*!< Integer id for shared memory buffer. */
} THD_datablock ;

The int type field is a code that indicates that this struct is a THD_datablock. The idea I had at the origin of AFNI was that each struct type would start with the field int type;, and each struct type would get a different integer code. Then it would be possible to detect the struct type in a generic processing routine, or at least do some error checking. The generic processing never happened, but the error checking does: the ISVALID_DATABLOCK() macro checks if the input pointer is non-NULL and if its type field is DATABLOCK_TYPE.

The crucial int nvals field stores the number of 3D sub-bricks in the dataset.

The even more crucial MRI_IMARR *brick field is the array of MRI_IMAGE structs that hold the actual data. This field, and a number of others, are initialized by the function THD_init_datablock_brick(). When initialized, all the MRI_IMAGEs within are "empty" (have NULL data pointers). Other fields that refer to the sub-brick storage and that are initialized by THD_init_datablock_brick() are:

  • float *brick_fac = pointer to an array of nvals floats; if brick_fac[i] > 0, then the values stored in the ith MRI_IMAGE should be scaled by brick_fac[i] to get the "true" values. The macro DSET_BRICK_FACTOR() will access these values.

  • int *brick_bytes = pointer to an array indicating the size of the data stored in each sub-brick of the dataset; the macro DSET_BRICK_BYTES() will access these values.

  • int64_t total_bytes = the sum of all the values in brick_bytes; this was recently changed to be a 64-bit integer to allow for super-sized datasets.
Because of the "array of arrays" storage paradigm for AFNI datasets, it is quite practical for a dataset to be larger than 2 GB. Requirements for such large datasets are that pointers are 64 bits, and that no individual sub-brick is over 2 GB in size (since ints are used for indexing throughout the AFNI code).

The next set of datablock components are loosely referred to as "brick auxiliary data"; each of these is an array of length nvals, storing information about each sub-brick. The functions in file thd_auxdata.c deal with this data:

  • char **brick_lab = array of labels for sub-bricks; for example, these are the labels that appear on the sub-brick menus in the "Define Overlay" control panel. These values are setup by THD_init_datablock_labels() and THD_store_datablock_label(). The macro DSET_BRICK_LAB() will access these values.

  • char **brick_keywords = array of keyword strings for sub-bricks. These values aren't used anywhere; they were an idea for which the world is not yet ready.

  • int *brick_statcode = array of codes indicating to which statistical distribution the values in a sub-brick belong. The statistical codes range from 2 to 10 (e.g., FUNC_TT_TYPE==3 for a t-statistic), and are used (along with brick_stataux) to determine the p-value associated with a threshold. These values are accessed by macro DSET_BRICK_STATCODE(); 0 indicates no distribution is to be used.

  • float **brick_stataux = array of pointers to float arrays which hold auxiliary statistical parameters for the various distributions; the kth parameter for the ith sub-brick is brick_stataux[i][k]. These values are accessed by macro DSET_BRICK_STATAUX() and DSET_BRICK_STATPAR().

--------MORE TO COME--------

Blog
« April 2024 »
Su Mo Tu We Th Fr Sa
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
 
 

Powered by Plone

This site conforms to the following standards: