Tag Points

Tag points are sets of three dimensional points which are used to mark positions of interest. Generally these result from manually locating corresponding positions in multiple volumes to provide a mapping among the volumes. Tag points are stored in an ascii format devised at the McConnell Brain Imaging Centre, with a convention of filenames ending in .tag. A tag file can contain either sets of single tag points or two tag points, depending on whether the file corresponds to one or two volumes. Each tag point consists of three coordinates, x, y, and z. Each set of one or two tag points has additional optional information stored with it. A tag point set may or may not include a set of three values: a real valued weight, an integer structure id, and an integer patient id. A tag point may or may not include a label string. Functions to read and write files of this format are described:

public  Status  input_tag_points(
    FILE      *file,
    int       *n_volumes,
    int       *n_tag_points,
    Real      ***tags_volume1,
    Real      ***tags_volume2,
    Real      **weights,
    int       **structure_ids,
    int       **patient_ids,
    STRING    *labels[] )
public  Status  input_tag_file(
    STRING    filename,
    int       *n_volumes,
    int       *n_tag_points,
    Real      ***tags_volume1,
    Real      ***tags_volume2,
    Real      **weights,
    int       **structure_ids,
    int       **patient_ids,
    STRING    *labels[] )

These two functions read a set of tag points from a file. The first form assumes the file is already open and will be closed by the calling function, while the second form opens and closes the file specified by a filename, with a default extension of .tag. The number of volumes (number of tags in a set, currently either one or two) is passed back in the n_volumes argument. The number of tag points is passed back in the n_tag_points argument. The three dimensional coordinates of the first tag point in each set is passed back in the argument tags_volume1. If the number of volumes is two, then the second tag point in each set is passed back in the argument tags_volume2. The final four arguments pass back the auxiliary information associated with each tag point set. If the calling program is not interested in any one of the four data, then it can pass in a NULL pointer and the values in the file will not be passed back.

public  void  free_tag_points(
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )

When finished with a list of tag points, the associated memory may be freed by calling this function.

public  Status  initialize_tag_file_input(
    FILE      *file,
    int       *n_volumes )
public  BOOLEAN  input_one_tag(
    FILE      *file,
    int       n_volumes,
    Real      tag_volume1[],
    Real      tag_volume2[],
    Real      *weight,
    int       *structure_id,
    int       *patient_id,
    STRING    *label,
    Status    *status )

These two routines provide a more memory efficient method to input tag points. After opening a file, the first routine is called to initialize the input of tags. The next routine is repeatedly called until it returns FALSE, reading one tag at a time.

public  Status  output_tag_points(
    FILE      *file,
    STRING    comments,
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )
public  Status  output_tag_file(
    STRING    filename,
    STRING    comments,
    int       n_volumes,
    int       n_tag_points,
    Real      **tags_volume1,
    Real      **tags_volume2,
    Real      weights[],
    int       structure_ids[],
    int       patient_ids[],
    STRING    labels[] )

These two functions write a list of tag points to a tag point file. The first form assumes that the file has already been opened and will be closed later by the calling function, while the second form opens and closes the file, with the default extension of .tag. The comments argument is any arbitrary string documenting the contents of this file. The number of volumes (n_volumes) must be either one or two. The number of tag points is specified by the argument n_tag_points. The positions of the sets of one or two tag points are in the arguments tags_volume1 and tags_volume2. If any of the three arguments, weights, structure_ids, or patient_ids, are specified as NULL, then none of these three pieces or information is written to the file. Similarly, if the labels argument is NULL, then no labels are written to the file.

public  STRING  get_default_tag_file_suffix()

Returns a pointer to a string consisting of the default suffix for tag point files, currently ``tag''. This pointer should not be freed or its contents modified.

public  Status  initialize_tag_file_output(
    FILE      *file,
    STRING    comments,
    int       n_volumes )
public  Status  output_one_tag(
    FILE      *file,
    int       n_volumes,
    Real      tag_volume1[],
    Real      tag_volume2[],
    Real      *weight,
    int       *structure_id,
    int       *patient_id,
    STRING    label )
public  void  terminate_tag_file_output(
    FILE    *file )

These two routines provide a more memory efficient method to output tag points. After opening a file, the first routine is called to initialize the output of tags. The next routine is repeatedly called to output a single tag point each time. The third routine is called to indicate the end of tag files.

Tag Points Source Code Example

The following is an example which reads a tag volume, removes all tags which have negative x positions, ignores the second tag point in each set, if present, and writes the result to a new file.

#include  <volume_io.h>
int  main(
    int   argc,
    char  *argv[] )
{
    int        i, n_volumes, n_tag_points, *structure_ids, *patient_ids;
    Real       **tags1, **tags2, *weights;
    STRING     *labels;
    int        new_n_tag_points, *new_structure_ids, *new_patient_ids;
    Real       **new_tags1, *new_weights;
    STRING     *new_labels;
    /*--- input the tag file */
    if( input_tag_file( "input_tags.tag", &n_volumes, &n_tag_points,
                        &tags1, &tags2, &weights, &structure_ids,
                        &patient_ids, &labels ) != OK )
        return( 1 );
    /*--- create a new tag point list of only those tag points
          whose x coordinate is nonnegative */
    new_n_tag_points = 0;
    for_less( i, 0, n_tag_points )
    {
        if( tags1[i][0] >= 0.0 )
        {
            /*--- increase the memory allocation of the tag points */
            SET_ARRAY_SIZE( new_tags1, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            ALLOC( new_tags1[new_n_tag_points], 3 );
            SET_ARRAY_SIZE( new_weights, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            SET_ARRAY_SIZE( new_structure_ids, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            SET_ARRAY_SIZE( new_patient_ids, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            SET_ARRAY_SIZE( new_labels, new_n_tag_points,
                            new_n_tag_points+1, 10 );
            ALLOC( new_labels[new_n_tag_points], strlen(labels[i])+1 );
            /*--- copy from the input tags to the new tags */
            new_tags1[new_n_tag_points][0] = tags1[i][0];
            new_tags1[new_n_tag_points][1] = tags1[i][1];
            new_tags1[new_n_tag_points][2] = tags1[i][2];
            new_weights[new_n_tag_points] = weights[i];
            new_structure_ids[new_n_tag_points] = structure_ids[i];
            new_patient_ids[new_n_tag_points] = patient_ids[i];
            (void) strcpy( new_labels[new_n_tag_points], labels[i] );
            /*--- increment the number of new tags */
            ++new_n_tag_points;
        }
    }
    /*--- output the new tags, the subset of the input tags */
    if( output_tag_file( "output.tag", "Removed negative X's",
                         1, new_n_tag_points, new_tags1, NULL,
                         new_weights, new_structure_ids,
                         new_patient_ids, new_labels ) != OK )
        return( 1 );
    return( 0 );
}