The THD_3dim_dataset struct (incomplete)
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.
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--------