Beispiel #1
0
image_metadata * read_minc(char *filename, float **image, int *sizes){
  VIO_Volume volume;
  VIO_Real dummy[3];
  image_metadata *meta;
  
  if( input_volume(filename, 3, NULL, NC_UNSPECIFIED, FALSE, 0.0, 0.0, TRUE, &volume, (minc_input_options *) NULL ) != VIO_OK )
      return( NULL );

    meta = (image_metadata *)calloc( 1 , sizeof(image_metadata) ) ;
    meta->start  = calloc(3,sizeof(float));
    meta->step   = calloc(3,sizeof(float));
    meta->length = calloc(3,sizeof(int));

    get_volume_sizes(volume,sizes);
    *image=malloc(sizes[0]*sizes[1]*sizes[2]*sizeof(**image));
    set_volume(*image, volume, sizes);

    meta->length[0]=sizes[0];
    meta->length[1]=sizes[1];
    meta->length[2]=sizes[2];    

    get_volume_starts(volume,dummy);
    meta->start[0]=dummy[0];
    meta->start[1]=dummy[1];
    meta->start[2]=dummy[2];

    get_volume_separations(volume,dummy);
    meta->step[0]=dummy[0];
    meta->step[1]=dummy[1];
    meta->step[2]=dummy[2];

    delete_volume(volume);
    
    return meta;
}
Beispiel #2
0
VIOAPI  void  cancel_volume_input(
    VIO_Volume            volume,
    volume_input_struct   *input_info )
{
    delete_volume( volume );
    delete_volume_input( input_info );
}
Beispiel #3
0
int write_minc(char *filename, float *image, image_metadata *meta,VIO_BOOL binary_mask){
  VIO_Volume volume;
  int i,j,k,index;
  float min=FLT_MAX,max=FLT_MIN;
  VIO_Real dummy[3];

  if(binary_mask)
  {
    volume = create_volume(3,NULL,NC_BYTE,FALSE,0.0,1.0);
    printf("Writing a binary volume...\n");
  }
  else 
    volume = create_volume(3,NULL,NC_FLOAT,FALSE,FLT_MIN,FLT_MAX);
  
  if(!volume)
    return STATUS_ERR;
  
  if(!binary_mask)
  {
    for (i=0;i<meta->length[0];i++){
      for (j=0;j<meta->length[1];j++){
        for (k=0;k<meta->length[2];k++){	  
          index=i*meta->length[2]*meta->length[1] + j*meta->length[2] + k;
          min=MIN(min,image[index]);
          max=MAX(max,image[index]);
        }
      }
    }
    set_volume_real_range(volume,min,max);
  } else {
    set_volume_real_range(volume,0.0,1.0);
  }
  
  set_volume_sizes(volume,meta->length);
  dummy[0]=meta->start[0];
  dummy[1]=meta->start[1];
  dummy[2]=meta->start[2];
  set_volume_starts(volume,dummy);
  dummy[0]=meta->step[0];
  dummy[1]=meta->step[1];
  dummy[2]=meta->step[2];
  set_volume_separations(volume,dummy);

  alloc_volume_data(volume);
    
  get_volume(image, volume, meta->length);

  if(!binary_mask)
    output_volume( filename, NC_FLOAT,FALSE,min, max,volume,meta->history,(minc_output_options *)NULL);
  else
    output_volume( filename, NC_BYTE,FALSE,0, 1.0,volume,meta->history,(minc_output_options *)NULL);
    
  delete_volume(volume);

  return STATUS_OK;
}
Beispiel #4
0
VIOAPI  VIO_Status  input_volume(
    VIO_STR              filename,
    int                  n_dimensions,
    VIO_STR              dim_names[],
    nc_type              volume_nc_data_type,
    VIO_BOOL             volume_signed_flag,
    VIO_Real             volume_voxel_min,
    VIO_Real             volume_voxel_max,
    VIO_BOOL             create_volume_flag,
    VIO_Volume           *volume,
    minc_input_options   *options )
{
    VIO_Status           status;
    VIO_Real             amount_done;
    volume_input_struct  input_info;
    VIO_progress_struct  progress;
    static const int     FACTOR = 1000;
    VIO_Real             volume_min=0.0,volume_max=0.0;

    status = start_volume_input( filename, n_dimensions, dim_names,
                                 volume_nc_data_type, volume_signed_flag,
                                 volume_voxel_min, volume_voxel_max,
                                 create_volume_flag, volume, options,
                                 &input_info );

    if( status == VIO_OK )
    {
        initialize_progress_report( &progress, FALSE, FACTOR, "Reading Volume");

        while( input_more_of_volume( *volume, &input_info, &amount_done ) )
        {
            update_progress_report( &progress,
                                    VIO_ROUND( (VIO_Real) FACTOR * amount_done));
        }

        if (amount_done < 1.0)
        {
          status = VIO_ERROR;
        }

        terminate_progress_report( &progress );

        delete_volume_input( &input_info );

        if( !volume_is_alloced( *volume ) ) {
          delete_volume( *volume );
          *volume = NULL;
          status = VIO_ERROR;
        }
    }
    if (status == VIO_OK)
    {
      get_volume_voxel_range( *volume, &volume_min, &volume_max );
    }
    return( status );
}
Beispiel #5
0
/* perform an erosion on a volume */
Volume  *erosion_kernel(Kernel * K, Volume * vol)
{
   int      x, y, z, c;
   double   value;
   int      sizes[MAX_VAR_DIMS];
   progress_struct progress;
   Volume   tmp_vol;

   if(verbose){
      fprintf(stdout, "Erosion kernel\n");
      }
   get_volume_sizes(*vol, sizes);
   initialize_progress_report(&progress, FALSE, sizes[2], "Erosion");

   /* copy the volume */
   tmp_vol = copy_volume(*vol);

   for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){
      for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){
         for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){

            value = get_volume_real_value(tmp_vol, z, y, x, 0, 0);
            for(c = 0; c < K->nelems; c++){
               if(get_volume_real_value(*vol,
                                        z + K->K[c][2],
                                        y + K->K[c][1],
                                        x + K->K[c][0],
                                        0 + K->K[c][3], 0 + K->K[c][4]) > value){
                  set_volume_real_value(*vol,
                                        z + K->K[c][2],
                                        y + K->K[c][1],
                                        x + K->K[c][0],
                                        0 + K->K[c][3],
                                        0 + K->K[c][4], value * K->K[c][5]);
                  }
               }

            value = get_volume_real_value(tmp_vol, z, y, x, 0, 0);
            }
         }
      update_progress_report(&progress, z + 1);
      }

   delete_volume(tmp_vol);
   terminate_progress_report(&progress);
   return (vol);
   }
Beispiel #6
0
VIOAPI  VIO_Status  start_volume_input(
    VIO_STR             filename,
    int                 n_dimensions,
    VIO_STR             dim_names[],
    nc_type             volume_nc_data_type,
    VIO_BOOL            volume_signed_flag,
    VIO_Real            volume_voxel_min,
    VIO_Real            volume_voxel_max,
    VIO_BOOL            create_volume_flag,
    VIO_Volume          *volume,
    minc_input_options  *options,
    volume_input_struct *input_info )
{
    VIO_Status          status;
    int                 d;
    VIO_STR             expanded_filename;
    minc_input_options  default_options;
    status = VIO_OK;

    if( options == (minc_input_options *) NULL )
    {
        set_default_minc_input_options( &default_options );
        options = &default_options;
    }
    
    if( create_volume_flag || *volume == (VIO_Volume) NULL )
    {
        if( n_dimensions < 1 || n_dimensions > VIO_MAX_DIMENSIONS )
        {
            n_dimensions = VIO_MAX_DIMENSIONS;
        }

        if( dim_names == (VIO_STR *) NULL )
            dim_names = get_default_dim_names( n_dimensions );

        *volume = create_volume( n_dimensions, dim_names, volume_nc_data_type,
                                 volume_signed_flag,
                                 volume_voxel_min, volume_voxel_max );
    }
    else if( n_dimensions != get_volume_n_dimensions( *volume ) &&
             volume_is_alloced( *volume ) )
    {
        free_volume_data( *volume );
    }

    expanded_filename = expand_filename( filename );

    if (filename_extension_matches( expanded_filename, FREE_ENDING ) ) {
        input_info->file_format = FREE_FORMAT;
    }
#ifdef LIBMINC_NIFTI_SUPPORT
    else if (filename_extension_matches( expanded_filename, "mgh" ) ||
             filename_extension_matches( expanded_filename, "mgz" )
             ) {
        input_info->file_format = MGH_FORMAT; /* FreeSurfer */
    }
    else if (filename_extension_matches( expanded_filename, "nii" ) ||
             filename_extension_matches( expanded_filename, "hdr" )) {
        input_info->file_format = NII_FORMAT; /* NIfTI-1 */
    }
    else if (filename_extension_matches( expanded_filename, "nhdr" ) ||
             filename_extension_matches( expanded_filename, "nrrd" )) {
        input_info->file_format = NRRD_FORMAT; /* NRRD */
    }
#endif /*LIBMINC_NIFTI_SUPPORT*/
    else {

#if defined(HAVE_MINC1) && defined(HAVE_MINC2)
      if(options->prefer_minc2_api) {
#endif

#if defined(HAVE_MINC2)
        input_info->file_format = MNC2_FORMAT;
#endif
        
#if defined(HAVE_MINC1) && defined(HAVE_MINC2)
      } else {
#endif
#ifdef HAVE_MINC1
        input_info->file_format = MNC_FORMAT;
#endif
#if defined(HAVE_MINC1) && defined(HAVE_MINC2)
      } 
#endif
    }
    switch( input_info->file_format )
    {
#ifdef HAVE_MINC1
    case  MNC_FORMAT:
        if( !file_exists( expanded_filename ) )
        {
            file_exists_as_compressed( expanded_filename,
                                              &expanded_filename );
        }

        input_info->minc_file = initialize_minc_input( expanded_filename,
                                                       *volume, options );
        if( input_info->minc_file == (Minc_file) NULL )
            status = VIO_ERROR;
        else
        {
            for_less( d, 0, VIO_MAX_DIMENSIONS )
                input_info->axis_index_from_file[d] = d;
        }

        break;
#endif /*HAVE_MINC1*/

#ifdef HAVE_MINC2
      case  MNC2_FORMAT:
        input_info->minc_file = initialize_minc2_input( expanded_filename,
                                                       *volume, options );
        if( input_info->minc_file == (Minc_file) NULL )
            status = VIO_ERROR;
        else
        {
            for_less( d, 0, VIO_MAX_DIMENSIONS )
            input_info->axis_index_from_file[d] = d;
        }
        break;
#endif /*HAVE_MINC2*/
    case  FREE_FORMAT:
        status = initialize_free_format_input( expanded_filename,
                                               *volume, input_info );
        break;
        
#ifdef LIBMINC_NIFTI_SUPPORT
      case MGH_FORMAT:
        status = initialize_mgh_format_input( expanded_filename,
                                              *volume, input_info );
        break;
      case NII_FORMAT:
        status = initialize_nifti_format_input( expanded_filename,
                                                *volume, input_info );
        break;
      case NRRD_FORMAT:
        status = initialize_nrrd_format_input( expanded_filename,
                                               *volume, input_info );
        break;
#endif /*LIBMINC_NIFTI_SUPPORT*/
      default:
        /*Unsupported file format*/
        status = VIO_ERROR;
        break;
    }

    if( status != VIO_OK && create_volume_flag )
        delete_volume( *volume );

    delete_string( expanded_filename );

    return( status );
}
Beispiel #7
0
void normalize_data_to_match_target(VIO_Volume d1, VIO_Volume m1, VIO_Real thresh1,
                                           VIO_Volume d2, VIO_Volume m2, VIO_Real thresh2,
                                           Arg_Data *globals)
{

  VectorR
    vector_step;

  PointR
    starting_position,
    slice,
    row,
    col,
    pos2,
    voxel;

  double
    tx,ty,tz;
  int
    i,j,k,
    r,c,s;

  VIO_Real
    min_range, max_range,
    data_vox, data_val,
    value1, value2;
  
  VIO_Real
    t1,t2,                        /* temporary threshold values     */
    s1,s2,s3;                   /* to store the sums for f1,f2,f3 */
  float 
    *ratios,
    result;                                /* the result */
  int 
    sizes[VIO_MAX_DIMENSIONS],ratios_size,count1,count2;

  VIO_Volume 
    vol;

  VIO_progress_struct
    progress;

  VIO_Data_types 
    data_type;


  set_feature_value_threshold(d1,d2, 
                              &thresh1, &thresh2,
                              &t1,      &t2);                              

  if (globals->flags.debug) {
    print ("In normalize_data_to_match_target, thresh = %10.3f %10.3f\n",t1,t2) ;
  }

  ratios_size = globals->count[ROW_IND] * globals->count[COL_IND] * globals->count[SLICE_IND];

  ALLOC(ratios, ratios_size);  

  fill_Point( starting_position, globals->start[VIO_X], globals->start[VIO_Y], globals->start[VIO_Z]);

  s1 = s2 = s3 = 0.0;
  count1 = count2 = 0;

  for(s=0; s<=globals->count[SLICE_IND]; s++) {

    SCALE_VECTOR( vector_step, globals->directions[SLICE_IND], s);
    ADD_POINT_VECTOR( slice, starting_position, vector_step );

    for(r=0; r<=globals->count[ROW_IND]; r++) {
      
      SCALE_VECTOR( vector_step, globals->directions[ROW_IND], r);
      ADD_POINT_VECTOR( row, slice, vector_step );
      
      SCALE_POINT( col, row, 1.0); /* init first col position */
      for(c=0; c<=globals->count[COL_IND]; c++) {
        
        convert_3D_world_to_voxel(d1, Point_x(col), Point_y(col), Point_z(col), &tx, &ty, &tz);
        
        fill_Point( voxel, tx, ty, tz ); /* build the voxel POINT */
        
        if (point_not_masked(m1, Point_x(col), Point_y(col), Point_z(col))) {

          value1 = get_value_of_point_in_volume( Point_x(col), Point_y(col), Point_z(col), d1);

          if ( value1 > t1 ) {

            count1++;

            DO_TRANSFORM(pos2, globals->trans_info.transformation, col);
            
            convert_3D_world_to_voxel(d2, Point_x(pos2), Point_y(pos2), Point_z(pos2), &tx, &ty, &tz);
            
            fill_Point( voxel, tx, ty, tz ); /* build the voxel POINT */
        
            if (point_not_masked(m2, Point_x(pos2), Point_y(pos2), Point_z(pos2))) {

              value2 = get_value_of_point_in_volume( Point_x(pos2), Point_y(pos2), Point_z(pos2), d2);

              if ( (value2 > t2)  && 
                   ((value2 < -1e-15) || (value2 > 1e-15)) ) {
                  
                ratios[count2++] = value1 / value2 ;

                s1 += value1*value2;
                s2 += value1*value1;
                s3 += value2*value2;
                  
                
              } /* if voxel in d2 */
            } /* if point in mask volume two */
          } /* if voxel in d1 */
        } /* if point in mask volume one */
        
        ADD_POINT_VECTOR( col, col, globals->directions[COL_IND] );
        
      } /* for c */
    } /* for r */
  } /* for s */
  

  if (count2 > 0) {

    if (globals->flags.debug) (void)print ("Starting qsort of ratios...");


    qs_list (ratios,0,count2);

    if (globals->flags.debug) (void)print ("Done.\n");

    result = ratios[ (int)(count2/2) ];        /* the median value */

    if (globals->flags.debug) (void)print ("Normalization: %7d %7d -> %10.8f\n",count1,count2,result);

    if ( fabs(result) < 1e-15) {
      print_error_and_line_num("Error computing normalization ratio `%f'.",__FILE__, __LINE__, result);
    }
    else {

      data_type = get_volume_data_type(d1);



      
      switch( data_type ) {
      case SIGNED_BYTE: 
      case UNSIGNED_BYTE: 
      case SIGNED_SHORT: 
      case UNSIGNED_SHORT: 
	
	/* build temporary working volume */
	
	vol = copy_volume_definition_no_alloc(d1, NC_UNSPECIFIED, FALSE, 0.0, 0.0);
	get_volume_minimum_maximum_real_value(d1, &min_range, &max_range);
	min_range /= result;
	max_range /= result;
	set_volume_real_range(vol, min_range, max_range);
	get_volume_sizes(d1, sizes);
	
	initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1,
				   "Normalizing source data" );
	count1 = 0;
	
	/* reset values in the data volume */
	
	for(i=0; i<sizes[0]; i++)
	  for(j=0; j<sizes[1]; j++) {
	    count1++;
	    update_progress_report( &progress, count1);
	    for(k=0; k<sizes[2]; k++) {
	      GET_VOXEL_3D( data_vox,  d1, i, j, k );
	      data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox);
	      data_val /= result;
	      data_vox = CONVERT_VALUE_TO_VOXEL( vol, data_val);
	      SET_VOXEL_3D( d1 , i, j, k, data_vox );
	    }
	  }
	
	terminate_progress_report( &progress );
	
	set_volume_real_range(d1, min_range, max_range);
	
	if (globals->flags.debug) (void)print ("After normalization min,max, thresh = %f %f %f\n",
					       min_range, max_range, t1/result);
	
	delete_volume(vol);
	break;
	
      default:			/* then volume should be either float or double */
	
	get_volume_sizes(d1, sizes);
	initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1,
				   "Normalizing source data" );
	count1 = 0;
	
	/* nomalize the values in the data volume */
	
	for(i=0; i<sizes[0]; i++)
	  for(j=0; j<sizes[1]; j++) {
	    count1++;
	    update_progress_report( &progress, count1);
	    
	    for(k=0; k<sizes[2]; k++) {	/* it should be possible to directly stream through the voxels, without indexing... */
	      GET_VOXEL_3D( data_vox,  d1, i, j, k );
	      data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox);
	      data_val /= result;
	      data_vox = CONVERT_VALUE_TO_VOXEL( d1, data_val);
	      SET_VOXEL_3D( d1 , i, j, k, data_vox );
	    }
	  }
	terminate_progress_report( &progress );
      }
    }
    
  }
  FREE(ratios);

  
}
Beispiel #8
0
void make_zscore_volume(VIO_Volume d1, VIO_Volume m1, 
                               VIO_Real *threshold)
{
  unsigned long
    count;
  int 
    stat_count,
    sizes[VIO_MAX_DIMENSIONS],
    s,r,c;
  VIO_Real
    wx,wy,wz,
    valid_min_dvoxel, valid_max_dvoxel,
    min,max,
    sum, sum2, mean, var, std,
    data_vox,data_val,
    thick[VIO_MAX_DIMENSIONS];

  PointR 
    voxel;

  VIO_Volume 
    vol;

  VIO_progress_struct
    progress;

  /* get default information from data and mask */

  /* build temporary working volume */
 
  vol = copy_volume_definition(d1, NC_UNSPECIFIED, FALSE, 0.0, 0.0);
  set_volume_real_range(vol, MIN_ZRANGE, MAX_ZRANGE);
  get_volume_sizes(d1, sizes);
  get_volume_separations(d1, thick);
  get_volume_voxel_range(d1, &valid_min_dvoxel, &valid_max_dvoxel);

  /* initialize counters and sums */

  count  = 0;
  sum  = 0.0;
  sum2 = 0.0;
  min = 1e38;
  max = -1e38;
  stat_count = 0;

  initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1,
                             "Tally stats" );

                                /* do first pass, to get mean and std */
  for(s=0; s<sizes[0]; s++) {
    for(r=0; r<sizes[1]; r++) {
      for(c=0; c<sizes[2]; c++) {

        stat_count++;
        update_progress_report( &progress, stat_count);
        convert_3D_voxel_to_world(d1, (VIO_Real)s, (VIO_Real)r, (VIO_Real)c, &wx, &wy, &wz);

        if (m1 != NULL) {
          convert_3D_world_to_voxel(m1, wx, wy, wz, &Point_x(voxel), &Point_y(voxel), &Point_z(voxel));
        }
        else {
          wx = 0.0; wy = 0.0; wz = 0.0;
        }

        if (point_not_masked(m1, wx,wy,wz)) {
          
          GET_VOXEL_3D( data_vox,  d1 , s, r, c );

          if (data_vox >= valid_min_dvoxel && data_vox <= valid_max_dvoxel) { 

            data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox);
            
            if (data_val > *threshold) {
              sum  += data_val;
              sum2 += data_val*data_val;
              
              count++;
              
              if (data_val < min)
                min = data_val;
              else
                if (data_val > max)
                  max = data_val;
            }
          }
        }
      }
    }
  }
  terminate_progress_report( &progress );

  stat_count = 0;
  initialize_progress_report(&progress, FALSE, sizes[0]*sizes[1]*sizes[2] + 1,
                             "Zscore convert" );

                                /* calc mean and std */
  mean = sum / (float)count;
  var  = ((float)count*sum2 - sum*sum) / ((float)count*((float)count-1));
  std  = sqrt(var);

  min = 1e38;
  max = -1e38;

                                /* replace the voxel values */
  for(s=0; s<sizes[0]; s++) {
    for(r=0; r<sizes[1]; r++) {
      for(c=0; c<sizes[2]; c++) {
        
        stat_count++;
        update_progress_report( &progress, stat_count);

        GET_VOXEL_3D( data_vox,  d1, s, r, c );
        
        if (data_vox >= valid_min_dvoxel && data_vox <= valid_max_dvoxel) { 
          
          data_val = CONVERT_VOXEL_TO_VALUE(d1, data_vox);
          
          if (data_val > *threshold) {

                                /* instead of   
                                   data_val = CONVERT_VALUE_TO_VOXEL(d1, data_vox);
                                   i will use
                                   data_val = CONVERT_VALUE_TO_VOXEL(d1, vol);

                                   since the values in vol are changed with respect to the
                                   new z-score volume */

            data_val = (data_val - mean) / std;
            if (data_val< MIN_ZRANGE) data_val = MIN_ZRANGE;
            if (data_val> MAX_ZRANGE) data_val = MAX_ZRANGE;

            data_vox = CONVERT_VALUE_TO_VOXEL( vol, data_val);
            

            if (data_val < min) {
              min = data_val;
            }
            else {
              if (data_val > max)
                max = data_val;
            }
          }
          else
            data_vox = -DBL_MAX;   /* should be fill_value! */
          
          SET_VOXEL_3D( d1 , s, r, c, data_vox );
        }
        
      }
    }
  }

  terminate_progress_report( &progress );

  set_volume_real_range(d1, MIN_ZRANGE, MAX_ZRANGE);        /* reset the data volume's range */

  *threshold = (*threshold - mean) / std;

  delete_volume(vol);
  
}
Beispiel #9
0
/* xcorr = sum((a*b)^2) / (sqrt(sum(a^2)) * sqrt(sum(b^2))   */
VIO_Volume *lcorr_kernel(Kernel * K, VIO_Volume * vol, VIO_Volume *cmp)
{
   int      x, y, z, c;
   double   value, v1, v2;
   double   ssum_v1, ssum_v2, sum_prd, denom;
   int      sizes[MAX_VAR_DIMS];
   progress_struct progress;
   Volume   tmp_vol;
   
   if(verbose){
      fprintf(stdout, "Local Correlation kernel\n");
      }
   get_volume_sizes(*vol, sizes);
   initialize_progress_report(&progress, FALSE, sizes[2], "Local Correlation");

   /* copy the volume */
   tmp_vol = copy_volume(*vol);
   
   /* zero the output volume */
   for(z = sizes[0]; z--;){
      for(y = sizes[1]; y--;){
         for(x = sizes[2]; x--;){
            set_volume_voxel_value(*vol, z, y, x, 0, 0, 0);
            }
         }
      }
   
   /* set output range */
   set_volume_real_range(*vol, 0.0, 1.0);
   
   for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){
      for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){
         for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){
            
            /* init counters */
            ssum_v1 = ssum_v2 = sum_prd = 0;
            for(c = 0; c < K->nelems; c++){
               v1 = get_volume_real_value(tmp_vol,
                                          z + K->K[c][2],
                                          y + K->K[c][1],
                                          x + K->K[c][0], 0 + K->K[c][3],
                                          0 + K->K[c][4]) * K->K[c][5];
               v2 = get_volume_real_value(*cmp,
                                          z + K->K[c][2],
                                          y + K->K[c][1],
                                          x + K->K[c][0], 0 + K->K[c][3],
                                          0 + K->K[c][4]) * K->K[c][5];
               
               /* increment counters */
               ssum_v1 += v1*v1;
               ssum_v2 += v2*v2;
               sum_prd += v1*v2;
               }
            
            denom = sqrt(ssum_v1 * ssum_v2);
            value = (denom == 0.0) ? 0.0 : sum_prd / denom;
            
            set_volume_real_value(*vol, z, y, x, 0, 0, value);
            }
         }
      update_progress_report(&progress, z + 1);
      }
   terminate_progress_report(&progress);
   
   /* tidy up */
   delete_volume(tmp_vol);
   
   return (vol);
   }
Beispiel #10
0
/* resulting groups are sorted WRT size          */
Volume  *group_kernel(Kernel * K, Volume * vol, double bg)
{
   int      x, y, z;
   int      sizes[MAX_VAR_DIMS];
   progress_struct progress;
   Volume   tmp_vol;
   Kernel  *k1, *k2;

   unsigned int *equiv;
   unsigned int *counts;
   unsigned int *trans;
   unsigned int neighbours[K->nelems];

   /* counters */
   unsigned int c;
   unsigned int value;
   unsigned int group_idx;             /* label for the next group     */
   unsigned int num_groups;

   unsigned int min_label;
   unsigned int curr_label;
   unsigned int prev_label;
   unsigned int num_matches;

   /* structure for group data */
   Group_info *group_data;

   /* split the Kernel into forward and backwards kernels */
   k1 = new_kernel(K->nelems);
   k2 = new_kernel(K->nelems);
   split_kernel(K, k1, k2);

   setup_pad_values(k1);
   setup_pad_values(k2);

   if(verbose){
      fprintf(stdout, "Group kernel - background %g\n", bg);
      fprintf(stdout, "forward direction kernel:\n");
      print_kernel(k1);
      fprintf(stdout, "\nreverse direction kernel:\n");
      print_kernel(k2);
      }

   get_volume_sizes(*vol, sizes);
   initialize_progress_report(&progress, FALSE, sizes[2], "Groups");

   /* copy and then zero out the original volume */
   tmp_vol = copy_volume(*vol);
   for(z = sizes[0]; z--;){
      for(y = sizes[1]; y--;){
         for(x = sizes[2]; x--;){
            set_volume_voxel_value(*vol, z, y, x, 0, 0, 0);
            }
         }
      }

   /* pass 1 - forward direction (we assume a symmetric kernel) */

   /* our first group is given the label 1 */
   group_idx = 1;

   /* initialise the equiv and counts arrays */
   SET_ARRAY_SIZE(equiv, 0, group_idx, 500);
   equiv[0] = 0;

   SET_ARRAY_SIZE(counts, 0, group_idx, 500);
   counts[0] = 0;

   for(z = -k1->pre_pad[2]; z < sizes[0] - k1->post_pad[2]; z++){
      for(y = -k1->pre_pad[1]; y < sizes[1] - k1->post_pad[1]; y++){
         for(x = -k1->pre_pad[0]; x < sizes[2] - k1->post_pad[0]; x++){

            if(get_volume_voxel_value(tmp_vol, z, y, x, 0, 0) != bg){

               /* search this voxels neighbours */
               num_matches = 0;
               min_label = INT_MAX;

               for(c = 0; c < k1->nelems; c++){
                  value = (unsigned int)get_volume_voxel_value(*vol,
                                                               z + k1->K[c][2],
                                                               y + k1->K[c][1],
                                                               x + k1->K[c][0],
                                                               0 + k1->K[c][3],
                                                               0 + k1->K[c][4]);
                  if(value != 0){
                     if(value < min_label){
                        min_label = value;
                        }
                     neighbours[num_matches] = value;
                     num_matches++;
                     }
                  }

               switch (num_matches){
               case 0:
                  /* no neighbours, make a new label and increment */
                  set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) group_idx);

                  SET_ARRAY_SIZE(equiv, group_idx, group_idx + 1, 500);
                  equiv[group_idx] = group_idx;

                  SET_ARRAY_SIZE(counts, group_idx, group_idx + 1, 500);
                  counts[group_idx] = 1;

                  group_idx++;
                  break;

               case 1:
                  /* only one neighbour, no equivalences needed */
                  set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) min_label);
                  counts[min_label]++;
                  break;

               default:
                  /* more than one neighbour */

                  /* first sort the neighbours array */
                  qsort(&neighbours[0], (size_t) num_matches, sizeof(unsigned int),
                        &compare_ints);

                  /* find the minimum possible label for this voxel,    */
                  /* this is done by descending through each neighbours */
                  /* equivalences until an equivalence equal to itself  */
                  /* is found                                           */
                  prev_label = -1;
                  for(c = 0; c < num_matches; c++){
                     curr_label = neighbours[c];

                     /* recurse this label if we haven't yet */
                     if(curr_label != prev_label){
                        while(equiv[curr_label] != equiv[equiv[curr_label]]){
                           curr_label = equiv[curr_label];
                           }

                        /* check against the current minimum value */
                        if(equiv[curr_label] < min_label){
                           min_label = equiv[curr_label];
                           }
                        }

                     prev_label = neighbours[c];
                     }

                  /* repeat, setting equivalences to the min_label */
                  prev_label = -1;
                  for(c = 0; c < num_matches; c++){
                     curr_label = neighbours[c];

                     if(curr_label != prev_label){
                        while(equiv[curr_label] != equiv[equiv[curr_label]]){
                           curr_label = equiv[curr_label];

                           equiv[curr_label] = min_label;
                           }

                        /* set the label itself */
                        if(equiv[neighbours[c]] != min_label){
                           equiv[neighbours[c]] = min_label;
                           }
                        }

                     prev_label = neighbours[c];
                     }

                  /* finally set the voxel in question to the minimum value */
                  set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) min_label);
                  counts[min_label]++;
                  break;
                  }                       /* end case */

               }
            }
         }
      update_progress_report(&progress, z + 1);
      }
   terminate_progress_report(&progress);

   /* reduce the equiv and counts array */
   num_groups = 0;
   for(c = 0; c < group_idx; c++){

      /* if this equivalence is not resolved yet */
      if(c != equiv[c]){

         /* find the min label value */
         min_label = equiv[c];
         while(min_label != equiv[min_label]){
            min_label = equiv[min_label];
            }

         /* update the label and its counters */
         equiv[c] = min_label;
         counts[min_label] += counts[c];
         counts[c] = 0;
         }
      else {
         num_groups++;
         }
      }

   /* Allocate space for the array of groups */
   group_data = (Group_info *) malloc(num_groups * sizeof(Group_info));

   num_groups = 0;
   for(c = 0; c < group_idx; c++){
      if(counts[c] > 0){
         /* allocate space for this element */
         group_data[num_groups] = malloc(sizeof(group_info_struct));

         group_data[num_groups]->orig_label = equiv[c];
         group_data[num_groups]->count = counts[c];
         num_groups++;
         }
      }

   /* sort the groups by the count size */
   if(verbose){
      fprintf(stdout, "Found %d unique groups from %d, sorting...\n", num_groups,
              group_idx);
      }
   qsort(group_data, num_groups, sizeof(Group_info), &compare_groups);

   /* set up the transpose array */
   trans = (unsigned int *)malloc(sizeof(unsigned int) * group_idx);
   for(c = 0; c < num_groups; c++){
      trans[group_data[c]->orig_label] = c + 1; /* +1 to bump past 0 */
      }

   /* pass 2 - resolve equivalences in the output data */
   if(verbose){
      fprintf(stdout, "Resolving equivalences...\n");
      }
   for(z = sizes[0]; z--;){
      for(y = sizes[1]; y--;){
         for(x = sizes[2]; x--;){
            value = (unsigned int)get_volume_voxel_value(*vol, z, y, x, 0, 0);
            if(value != 0){
               value = trans[equiv[value]];
               set_volume_voxel_value(*vol, z, y, x, 0, 0, (Real) value);
               }
            }
         }
      }

   /* tidy up */
   delete_volume(tmp_vol);
   for(c = 0; c < num_groups; c++){
      free(group_data[c]);
      }
   free(group_data);
   free(trans);
   free(k1);
   free(k2);

   return (vol);
   }
Beispiel #11
0
/* perform a median kernel operation on a volume */
Volume  *median_dilation_kernel(Kernel * K, Volume * vol)
{
   int      x, y, z, c, i;
   int      sizes[MAX_VAR_DIMS];
   progress_struct progress;
   Volume   tmp_vol;
   double   value;

   unsigned int kvalue;
   unsigned int neighbours[K->nelems];

   if(verbose){
      fprintf(stdout, "Median Dilation kernel\n");
      }
   get_volume_sizes(*vol, sizes);
   initialize_progress_report(&progress, FALSE, sizes[2], "Median Dilation");

   /* copy the volume */
   tmp_vol = copy_volume(*vol);

   for(z = -K->pre_pad[2]; z < sizes[0] - K->post_pad[2]; z++){
      for(y = -K->pre_pad[1]; y < sizes[1] - K->post_pad[1]; y++){
         for(x = -K->pre_pad[0]; x < sizes[2] - K->post_pad[0]; x++){

            /* only modify background voxels */
            value = get_volume_voxel_value(tmp_vol, z, y, x, 0, 0);
            if(value == 0.0){

               i = 0;
               for(c = 0; c < K->nelems; c++){

                  kvalue = (unsigned int)get_volume_voxel_value(tmp_vol,
                                                                z + K->K[c][2],
                                                                y + K->K[c][1],
                                                                x + K->K[c][0],
                                                                0 + K->K[c][3],
                                                                0 + K->K[c][4]);
                  if(kvalue != 0){
                     neighbours[i] = kvalue;
                     i++;
                     }
                  }

               /* only run this for adjacent voxels */
               if(i > 0){

                  /* find the median of our little array */
                  qsort(&neighbours[0], (size_t) i, sizeof(unsigned int), &compare_ints);

                  /* store the median value */
                  set_volume_voxel_value(*vol, z, y, x, 0, 0,
                                         (double)neighbours[(int)floor((i - 1) / 2)]);
                  }
               }

            /* else just copy the original value over */
            else {
               set_volume_voxel_value(*vol, z, y, x, 0, 0, value);
               }
            }
         }

      update_progress_report(&progress, z + 1);
      }

   delete_volume(tmp_vol);
   terminate_progress_report(&progress);
   return (vol);
   }
Beispiel #12
0
int main(int argc, char *argv[])
{
   char   **infiles;
   int      n_infiles;
   char    *out_fn;
   char    *history;
   VIO_progress_struct progress;
   VIO_Volume   totals, weights;
   int      i, j, k, v;
   double   min, max;
   double   w_min, w_max;
   long     num_missed;
   double   weight, value;
   double   initial_weight;

   VIO_Real     dummy[3];

   int      sizes[MAX_VAR_DIMS];
   double   starts[MAX_VAR_DIMS];
   double   steps[MAX_VAR_DIMS];
   
   long     t = 0;

   /* start the time counter */
   current_realtime_seconds();
   
   /* get the history string */
   history = time_stamp(argc, argv);

   /* get args */
   if(ParseArgv(&argc, argv, argTable, 0) || (argc < 3)){
      fprintf(stderr,
              "\nUsage: %s [options] <in1.mnc> [<in2.mnc> [...]] <out.mnc>\n", argv[0]);
      fprintf(stderr,
              "       %s [options] -arb_path pth.conf <infile.raw> <out.mnc>\n", argv[0]);
      fprintf(stderr, "       %s -help\n\n", argv[0]);
      exit(EXIT_FAILURE);
      }

   /* get file names */
   n_infiles = argc - 2;
   infiles = (char **)malloc(sizeof(char *) * n_infiles);
   for(i = 0; i < n_infiles; i++){
      infiles[i] = argv[i + 1];
      }
   out_fn = argv[argc - 1];

   /* check for infiles and outfile */
   for(i = 0; i < n_infiles; i++){
      if(!file_exists(infiles[i])){
         fprintf(stderr, "%s: Couldn't find input file %s.\n\n", argv[0], infiles[i]);
         exit(EXIT_FAILURE);
         }
      }
   if(!clobber && file_exists(out_fn)){
      fprintf(stderr, "%s: %s exists, -clobber to overwrite.\n\n", argv[0], out_fn);
      exit(EXIT_FAILURE);
      }

   /* check for weights_fn if required */
   if(weights_fn != NULL){
      if(!clobber && file_exists(weights_fn)){
         fprintf(stderr, "%s: %s exists, -clobber to overwrite.\n\n", argv[0],
                 weights_fn);
         exit(EXIT_FAILURE);
         }
      }

   /* set up parameters for reconstruction */
   if(out_dtype == NC_UNSPECIFIED){
      out_dtype = in_dtype;
      }
   if(out_is_signed == DEF_BOOL){
      out_is_signed = in_is_signed;
      }

   /* check vector dimension size */
   if(vect_size < 1){
      fprintf(stderr, "%s: -vector (%d) must be 1 or greater.\n\n", argv[0], vect_size);
      exit(EXIT_FAILURE);
      }

   /* check sigma */
   if(regrid_sigma[0] <= 0 || regrid_sigma[1] <= 0 || regrid_sigma[2] <= 0 ){
      fprintf(stderr, "%s: -sigma must be greater than 0\n\n", argv[0]);
      exit(EXIT_FAILURE);
      }

   /* read in the output file config from a file is specified */
   if(out_config_fn != NULL){
      int      ext_args_c;
      char    *ext_args[32];           /* max possible is 32 arguments */

      ext_args_c = read_config_file(out_config_fn, ext_args);
      if(ParseArgv(&ext_args_c, ext_args, argTable,
                   ARGV_DONT_SKIP_FIRST_ARG | ARGV_NO_LEFTOVERS | ARGV_NO_DEFAULTS)){
         fprintf(stderr, "\nError in parameters in %s\n", out_config_fn);
         exit(EXIT_FAILURE);
         }
      }

   if(verbose){
      fprintf_vol_def(stdout, &out_inf);
      }

   /* transpose the geometry arrays */
   /* out_inf.*[] are in world xyz order, perm[] is the permutation
      array to map world xyz to the right voxel order in the volume */
   for(i = 0; i < WORLD_NDIMS; i++){
      sizes[i] = out_inf.nelem[perm[i]];  /* sizes, starts, steps are in voxel volume order. */
      starts[i] = out_inf.start[perm[i]];
      steps[i] = out_inf.step[perm[i]];
      }
   sizes[WORLD_NDIMS] = vect_size;

   /* create the totals volume */
   totals = create_volume((vect_size > 1) ? 4 : 3,
                          (vect_size > 1) ? std_dimorder_v : std_dimorder,
                          out_dtype, out_is_signed, 0.0, 0.0);
   set_volume_sizes(totals, sizes);
   set_volume_starts(totals, starts);
   set_volume_separations(totals, steps);
   for(i = 0; i < WORLD_NDIMS; i++){
      /* out_inf.dircos is in world x,y,z order, we have to use the perm array to 
         map each direction to the right voxel axis. */
      set_volume_direction_cosine(totals, i, out_inf.dircos[perm[i]]);
      }
   alloc_volume_data(totals);

   /* create the "weights" volume */
   weights = create_volume(3, std_dimorder, out_dtype, out_is_signed, 0.0, 0.0);
   set_volume_sizes(weights, sizes);
   set_volume_starts(weights, starts);
   set_volume_separations(weights, steps);
   for(i = 0; i < WORLD_NDIMS; i++){
      set_volume_direction_cosine(weights, i, out_inf.dircos[perm[i]]);
      }
   alloc_volume_data(weights);

   /* down below in regrid_loop, Andrew makes a nasty direct reference to the
      voxel_to_world transformation in the volume.  This
      transformation is not necessarily up to date, particularly when
      non-default direction cosines are used.  In volume_io, the
      direction cosines are set and a FLAG is also set to indicate
      that the voxel-to-world xform is not up to date.  If the stanrd
      volume_io general transform code is used, it checks internally
      to see if the matrix is up to date, and if not it is recomputed.

      So here, we'll (LC + MK) force an update by calling a general
      transform.  */

//   convert_world_to_voxel(weights, (Real) 0, (Real) 0, (Real) 0, dummy);
//   convert_world_to_voxel(totals, (Real) 0, (Real) 0, (Real) 0, dummy);

   fprintf(stderr, "2Sizes: [%d:%d:%d] \n", sizes[perm[0]], sizes[perm[1]], sizes[perm[2]]);
   
   /* initialize weights to be arbitray large value if using NEAREST */
   /* volume interpolation else initialize all to zero */
   if(regrid_type == NEAREST_FUNC && ap_coord_fn == NULL){
      initial_weight = LARGE_INITIAL_WEIGHT;
      }
   else{
      initial_weight = 0.0;
      }
   
   /* initialize weights and totals */   
   for(k = sizes[Z_IDX]; k--;){
      for(j = sizes[Y_IDX]; j--;){
         for(i = sizes[X_IDX]; i--;){
            set_volume_real_value(weights, k, j, i, 0, 0, initial_weight);
            for(v = vect_size; v--;){
               set_volume_real_value(totals, k, j, i, v, 0, 0.0);
               }
            }
         }
      }

   /* if regridding via an arbitrary path */
   if(ap_coord_fn != NULL){

      if(n_infiles > 1){
         fprintf(stderr, "%s: arb_path only works for one input file (so far).\n\n",
                 argv[0]);
         exit(EXIT_FAILURE);
         }

      /* print some pretty output */
      if(verbose){
         fprintf(stdout, " | Input data:      %s\n", infiles[0]);
         fprintf(stdout, " | Arb path:        %s\n", ap_coord_fn);
         fprintf(stdout, " | Output range:    [%g:%g]\n", out_range[0], out_range[1]);
         fprintf(stdout, " | Output file:     %s\n", out_fn);
         }

      regrid_arb_path(ap_coord_fn, infiles[0], max_buffer_size_in_kb,
                      &totals, &weights, vect_size, regrid_range[0], regrid_range[1]);
      }

   /* else if regridding via a series of input minc file(s) */
   else {
      for(i = 0; i < n_infiles; i++){
         if(verbose){
            fprintf(stdout, " | Input file:      %s\n", infiles[i]);
            }
         regrid_minc(infiles[i], max_buffer_size_in_kb,
                     &totals, &weights, vect_size, regrid_range[0], regrid_range[1]);
         }
      }

   /* initialise min and max counters and divide totals/weights */
   num_missed = 0;
   min = get_volume_real_value(totals, 0, 0, 0, 0, 0);
   max = get_volume_real_value(totals, 0, 0, 0, 0, 0);
   w_min = get_volume_real_value(weights, 0, 0, 0, 0, 0);
   w_max = get_volume_real_value(weights, 0, 0, 0, 0, 0);
   initialize_progress_report(&progress, FALSE, out_inf.nelem[Z_IDX], "Dividing through");
   
   for(i = sizes[perm[0]]; i--;){
      for(j = sizes[perm[1]]; j--;){
         for(k = sizes[perm[2]]; k--;){
            weight = get_volume_real_value(weights, k, j, i, 0, 0);
            if(weight < w_min){
               w_min = weight;
               }
            else if(weight > w_max){
               w_max = weight;
               }
            
            if(weight != 0){
               for(v = vect_size; v--;){
                  value = get_volume_real_value(totals, k, j, i, v, 0) / weight;
                  if(value < min){
                     min = value;
                     }
                  else if(value > max){
                     max = value;
                     }
                  
                  set_volume_real_value(totals, k, j, i, v, 0, value);
                  }
               }
            else {
               num_missed++;
               }
            }
         }
      update_progress_report(&progress, k + 1);
      }
   terminate_progress_report(&progress);

   /* set the volumes range */
   if(verbose){
      fprintf(stdout, " + data range:   [%g:%g]\n", min, max);
      fprintf(stdout, " + weight range: [%g:%g]\n", w_min, w_max);
      }
   set_volume_real_range(totals, min, max);
   set_volume_real_range(weights, w_min, w_max);

   if(num_missed > 0 && verbose){
      int      nvox;

      nvox = out_inf.nelem[X_IDX] * out_inf.nelem[Y_IDX] * out_inf.nelem[Z_IDX];
      fprintf(stdout,
              "\n-regrid_radius possibly too small, no data in %ld/%d[%2.2f%%] voxels\n\n",
              num_missed, nvox, ((float)num_missed / nvox * 100));
      }

   /* rescale data if required */
   if(out_range[0] != -DBL_MAX && out_range[1] != DBL_MAX){
      double   o_min, o_max;

      /* get the existing range */
      get_volume_real_range(totals, &o_min, &o_max);

      /* rescale it */
      scale_volume(&totals, o_min, o_max, out_range[0], out_range[1]);
      }

   /* output the result */
   if(verbose){
      fprintf(stdout, " | Outputting %s...\n", out_fn);
      }
   if(output_volume(out_fn, out_dtype, out_is_signed,
                    0.0, 0.0, totals, history, NULL) != VIO_OK){
      fprintf(stderr, "Problems outputing: %s\n\n", out_fn);
      }

   /* output weights volume if required */
   if(weights_fn != NULL){
      if(verbose){
         fprintf(stdout, " | Outputting %s...\n", weights_fn);
         }
      if(output_volume(weights_fn, out_dtype, out_is_signed,
                       0.0, 0.0, weights, history, NULL) != VIO_OK){
         fprintf(stderr, "Problems outputting: %s\n\n", weights_fn);
         }
      }

   delete_volume(totals);
   delete_volume(weights);
   
   t = current_realtime_seconds();
   printf("Total reconstruction time: %ld hours %ld minutes %ld seconds\n", t/3600, (t/60)%60, t%60);
   
   return (EXIT_SUCCESS);
   }
Beispiel #13
0
int  main(
    int   argc,
    char  *argv[] )
{
    Volume         volume;
    STRING         input_filename, output_filename;
    int            n_slices, n_components;
    pixels_struct  *pixels;
    nc_type        vol_type;
    BOOLEAN        two_d_allowed;

    initialize_argument_processing( argc, argv );

    if( !get_string_argument( NULL, &output_filename ) ||
        !get_int_argument( 0, &n_components ) )
    {
        print( "Usage: %s output.mnc  3|4|23|24 input1.rgb input2.rgb ...\n", argv[0] );
        return( 1 );
    }

    if( n_components > 100 )
    {
        vol_type = NC_FLOAT;
        n_components -= 100;
    }
    else
        vol_type = NC_BYTE;

    if( n_components > 20 )
    {
        two_d_allowed = TRUE;
        n_components -= 20;
    }
    else
    {
        two_d_allowed = FALSE;
    }

    n_slices = 0;
    pixels = NULL;

    while( get_string_argument( "", &input_filename ) )
    {
        SET_ARRAY_SIZE( pixels, n_slices, n_slices+1, DEFAULT_CHUNK_SIZE );

        if( input_rgb_file( input_filename, &pixels[n_slices] ) != OK )
            return( 1 );

        ++n_slices;
    }

    volume = convert_pixels_to_volume( n_components, n_slices,
                                       (two_d_allowed && n_slices == 1) ? 2 : 3,
                                       vol_type, pixels );

    if( volume != NULL )
    {
        (void) output_volume( output_filename, NC_UNSPECIFIED, FALSE,
                              0.0, 0.0,
                              volume, "Converted from pixels",
                              (minc_output_options *) NULL );

        delete_volume( volume );
    }

    return( 0 );
}
static void append_new_default_deformation_field(Arg_Data *globals)
{

  VIO_Volume
    new_field;
  VIO_Real
    zero,
    st[VIO_MAX_DIMENSIONS],
    wst[VIO_MAX_DIMENSIONS],
    step[VIO_MAX_DIMENSIONS],
    XYZstart[ VIO_MAX_DIMENSIONS ],
    XYZstep[ VIO_MAX_DIMENSIONS ],
    voxel[VIO_MAX_DIMENSIONS],
    point[VIO_N_DIMENSIONS],
    dir[3][3];

  int
    index[VIO_MAX_DIMENSIONS],
    xyzv[VIO_MAX_DIMENSIONS],
    i,
    count[VIO_MAX_DIMENSIONS],
    XYZcount[VIO_MAX_DIMENSIONS],
    count_extended[VIO_MAX_DIMENSIONS];

  VIO_General_transform
    *grid_trans;

   VectorR
    XYZdirections[ VIO_MAX_DIMENSIONS ];

  /* build a vector volume to store the Grid VIO_Transform */

   /*  ALLOC(new_field,1); not needed since create volume allocs it
       internally and returns a pointer*/

  if (globals->flags.debug) { print ("In append_new_default_deformation_field...\n"); }

  new_field = create_volume(4, dim_name_vector_vol, NC_DOUBLE, TRUE, 0.0, 0.0);

  get_volume_XYZV_indices(new_field, xyzv);

                                /* get the global voxel count and voxel size */
  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    count[xyzv[i]] = globals->count[i];
    count_extended[xyzv[i]] = count[xyzv[i]];
    step[xyzv[i]]  = globals->step[i];
  }
                                /* add info for the vector dimension */
  count[xyzv[VIO_Z+1]] = 3;
  count_extended[xyzv[VIO_Z+1]] = 3;
  step[xyzv[VIO_Z+1]] = 0.0;


  set_volume_sizes(       new_field, count);
  set_volume_separations( new_field, step);
  /*
     set_volume_voxel_range( new_field, -MY_MAX_VOX, MY_MAX_VOX);
     set_volume_real_range(  new_field, -1.0*globals->trans_info.max_def_magnitude, globals->trans_info.max_def_magnitude); no longer needed, now using floats */


  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    dir[VIO_X][i]=globals->directions[VIO_X].coords[i];
    dir[VIO_Y][i]=globals->directions[VIO_Y].coords[i];
    dir[VIO_Z][i]=globals->directions[VIO_Z].coords[i];

  }


  set_volume_direction_cosine(new_field,xyzv[VIO_X],dir[VIO_X]);
  set_volume_direction_cosine(new_field,xyzv[VIO_Y],dir[VIO_Y]);
  set_volume_direction_cosine(new_field,xyzv[VIO_Z],dir[VIO_Z]);


  for(i=0; i<VIO_MAX_DIMENSIONS; i++)  /* set the voxel origin, used in the vol def */
    voxel[i] = 0.0;

  set_volume_translation( new_field, voxel, globals->start);



  if (globals->flags.debug) {
    print("in append new def, the start is: %8.3f %8.3f %8.3f\n", globals->start[VIO_X], globals->start[VIO_Y], globals->start[VIO_Z]);
  }

                   /* now pad the volume along the spatial axis
                      to ensure good coverage of the data space
                      with the deformation field */

  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    if (globals->count[i]>1) {
      voxel[xyzv[i]] = -2.5;
      count_extended[xyzv[i]] = globals->count[i]+5;
    }
    else {
      voxel[xyzv[i]] = 0.0;
      count_extended[xyzv[i]] = 1;
    }
  }

  if (globals->flags.debug) {
    print("in append_new_default_deformation_field:\n\tcount_extended= %d %d %d %d\n",
           count_extended[0],count_extended[1],count_extended[2],count_extended[3]);
  }

  set_volume_sizes(new_field, count_extended);
  for(i=0; i<VIO_MAX_DIMENSIONS; i++) count[i] = count_extended[i];

              /* reset the first voxel position with the new origin */
  convert_voxel_to_world(new_field, voxel,
                         &(point[VIO_X]), &(point[VIO_Y]), &(point[VIO_Z]));
  for(i=0; i<VIO_MAX_DIMENSIONS; i++) voxel[i] = 0;

  set_volume_translation(new_field, voxel, point);


  if (globals->flags.debug) {
    print (" point: %8.3f %8.3f %8.3f \n", point[VIO_X], point[VIO_Y], point[VIO_Z]);

    get_volume_starts(new_field, st);
    print (" start: %8.3f %8.3f %8.3f \n", st[xyzv[VIO_X]], st[xyzv[VIO_Y]], st[xyzv[VIO_Z]]);

    voxel[0] = 0;
    voxel[1] = 0;
    voxel[2] = 0;
    get_volume_translation(new_field, voxel, wst);
    print (" wstrt: %8.3f %8.3f %8.3f \n", wst[VIO_X], wst[VIO_Y], wst[VIO_Z]);
    print (" voxel: %8.3f %8.3f %8.3f \n", voxel[xyzv[VIO_X]], voxel[xyzv[VIO_Y]], voxel[xyzv[VIO_Z]]);


    for(i=0; i<3; i++) {
      get_volume_direction_cosine(new_field,xyzv[i], wst);
      print (" dirs: %8.3f %8.3f %8.3f \n", wst[VIO_X], wst[VIO_Y], wst[VIO_Z]);
    }



  }


              /* allocate space for the deformation field data */
  alloc_volume_data(new_field);

              /* Initilize the field to zero deformation */

  /* zero = CONVERT_VALUE_TO_VOXEL(new_field, 0.0); not needed, defs are now doubles */

  for(index[0]=0; index[0]<count[0]; index[0]++)
    for(index[1]=0; index[1]<count[1]; index[1]++)
      for(index[2]=0; index[2]<count[2]; index[2]++)
        for(index[3]=0; index[3]<count[3]; index[3]++)
          {
            SET_VOXEL(new_field, index[0],index[1],index[2],index[3],0, 0.0);  /* was set to 'zero', but now as a double,can be set to 0.0 */
          }

              /* build the new GRID_TRANSFORM */

  ALLOC(grid_trans, 1);

  create_grid_transform(grid_trans, new_field, NULL);

              /* append the deforamation to the current transformation */
  concat_general_transforms(globals->trans_info.transformation, grid_trans,
                            globals->trans_info.transformation);

  delete_volume(new_field);
  delete_general_transform(grid_trans);




}
static void resample_the_deformation_field(Arg_Data *globals)
{

  VIO_Volume
    existing_field,
    new_field;
  VIO_Real
    vector_val[3],
    XYZstart[ VIO_MAX_DIMENSIONS ],
    wstart[ VIO_MAX_DIMENSIONS ],
    start[    VIO_MAX_DIMENSIONS ],
    XYZstep[  VIO_MAX_DIMENSIONS ],
    step[     VIO_MAX_DIMENSIONS ],
    step2[    VIO_MAX_DIMENSIONS ],
    s1[       VIO_MAX_DIMENSIONS ],
    voxel[    VIO_MAX_DIMENSIONS ],
    dir[3][3];
  int
    i,
    siz[      VIO_MAX_DIMENSIONS ],
    index[    VIO_MAX_DIMENSIONS ],
    xyzv[     VIO_MAX_DIMENSIONS ],
    XYZcount[ VIO_MAX_DIMENSIONS ],
    count[    VIO_MAX_DIMENSIONS ];
  VIO_General_transform
    *non_lin_part;
  VectorR
    XYZdirections[ VIO_MAX_DIMENSIONS ];
  VIO_Real
    del_x, del_y, del_z, wx, wy,wz;
  VIO_progress_struct
    progress;
  char
    **data_dim_names;


                                /* get the nonlinear part
                                   of the transformation           */

  existing_field = (VIO_Volume)NULL;
  non_lin_part = get_nth_general_transform(globals->trans_info.transformation,
                                           get_n_concated_transforms(
                                               globals->trans_info.transformation)
                                           -1);

  if (get_transform_type( non_lin_part ) == GRID_TRANSFORM){
    existing_field = (VIO_Volume)(non_lin_part->displacement_volume);
  }
  else {
    for(i=0; i<get_n_concated_transforms(globals->trans_info.transformation); i++)
      print ("Transform %d is of type %d\n",i,
             get_transform_type(
                get_nth_general_transform(globals->trans_info.transformation,
                                i) ));

    print_error_and_line_num("Cannot find the deformation field transform to resample",
                             __FILE__, __LINE__);
  }

  /* build a vector volume to store the Grid VIO_Transform */

  new_field = create_volume(4, dim_name_vector_vol, NC_DOUBLE, TRUE, 0.0, 0.0);

  get_volume_XYZV_indices(new_field, xyzv);

  for(i=0; i<VIO_N_DIMENSIONS; i++)
    step2[i] = globals->step[i];
                                /* get new start, count, step and directions,
                                   all returned in X, Y, Z order.          */

  set_up_lattice(existing_field, step2, XYZstart, wstart, XYZcount, XYZstep, XYZdirections);

                                /* reset count and step to be in volume order */
  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    start[      i  ] = wstart[ i ];
    count[ xyzv[i] ] = XYZcount[ i ];
    step[  xyzv[i] ] = XYZstep[  i ];
  }

                                /* add info for the vector dimension */
  count[xyzv[VIO_Z+1]] = 3;
  step[xyzv[VIO_Z+1]] = 0.0;

         /* use the sign of the step returned to set the true step size */
  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    if (step[xyzv[i]]<0)
      step[xyzv[i]] = -1.0 * fabs(globals->step[i]);
    else
      step[xyzv[i]] = fabs(globals->step[i]);
  }

  for(i=0; i<VIO_MAX_DIMENSIONS; i++)  /* set the voxel origin, used in the vol def */
    voxel[i] = 0.0;

  set_volume_sizes(       new_field, count);
  set_volume_separations( new_field, step);

  /*  set_volume_voxel_range( new_field, -MY_MAX_VOX, MY_MAX_VOX);
      set_volume_real_range(  new_field, -1.0*globals->trans_info.max_def_magnitude, globals->trans_info.max_def_magnitude);  - no longer needed, because now using doubles*/

  set_volume_translation( new_field, voxel, start);

  for(i=0; i<VIO_N_DIMENSIONS; i++) {
    dir[VIO_X][i]=XYZdirections[VIO_X].coords[i];
    dir[VIO_Y][i]=XYZdirections[VIO_Y].coords[i];
    dir[VIO_Z][i]=XYZdirections[VIO_Z].coords[i];

  }


  set_volume_direction_cosine(new_field,xyzv[VIO_X],dir[VIO_X]);
  set_volume_direction_cosine(new_field,xyzv[VIO_Y],dir[VIO_Y]);
  set_volume_direction_cosine(new_field,xyzv[VIO_Z],dir[VIO_Z]);


                                /* make sure that the vector dimension
                                   is named! */
  data_dim_names = get_volume_dimension_names(new_field);

  if( strcmp( data_dim_names[ xyzv[VIO_Z+1] ] , MIvector_dimension ) != 0 ) {
    ALLOC((new_field)->dimension_names[xyzv[VIO_Z+1]], \
          strlen(MIvector_dimension  ) + 1 );
    (void) strcpy( (new_field)->dimension_names[xyzv[VIO_Z+1]], MIvector_dimension );
  }

  delete_dimension_names(new_field, data_dim_names);

  if (globals->flags.debug) {
    print ("in resample_deformation_field:\n");
    print ("xyzv[axes] = %d, %d, %d, %d\n",xyzv[VIO_X],xyzv[VIO_Y],xyzv[VIO_Z],xyzv[VIO_Z+1]);

    get_volume_sizes(new_field, siz);
    get_volume_separations(new_field, s1);
    print ("seps: %7.3f %7.3f %7.3f %7.3f %7.3f \n",s1[0],s1[1],s1[2],s1[3],s1[4]);
    print ("size: %7d %7d %7d %7d %7d \n",siz[0],siz[1],siz[2],siz[3],siz[4]);
  }

  alloc_volume_data(new_field);

  if (globals->flags.verbose>0)
    initialize_progress_report( &progress, FALSE, count[xyzv[VIO_X]],
                               "Interpolating new field" );

  /* now resample the values from the input deformation */

  for(i=0; i<VIO_MAX_DIMENSIONS; i++) {
    voxel[i] = 0.0;
    index[i] = 0;
  }

  for(index[xyzv[VIO_X]]=0; index[xyzv[VIO_X]]<count[xyzv[VIO_X]]; index[xyzv[VIO_X]]++) {
    voxel[xyzv[VIO_X]] = (VIO_Real)index[xyzv[VIO_X]];

    for(index[xyzv[VIO_Y]]=0; index[xyzv[VIO_Y]]<count[xyzv[VIO_Y]]; index[xyzv[VIO_Y]]++) {
      voxel[xyzv[VIO_Y]] = (VIO_Real)index[xyzv[VIO_Y]];

      for(index[xyzv[VIO_Z]]=0; index[xyzv[VIO_Z]]<count[xyzv[VIO_Z]]; index[xyzv[VIO_Z]]++) {
        voxel[xyzv[VIO_Z]] = (VIO_Real)index[xyzv[VIO_Z]];

        convert_voxel_to_world(new_field, voxel, &wx,&wy,&wz);


           grid_transform_point(non_lin_part, wx, wy, wz,
                             &del_x, &del_y, &del_z);



                                /* get just the deformation part */
        del_x = del_x - wx;
        del_y = del_y - wy;
        del_z = del_z - wz;


/*        del_x = del_y = del_z = 0.0;
*/
        vector_val[0] = CONVERT_VALUE_TO_VOXEL(new_field, del_x);
        vector_val[1] = CONVERT_VALUE_TO_VOXEL(new_field, del_y);
        vector_val[2] = CONVERT_VALUE_TO_VOXEL(new_field, del_z);

        for(index[xyzv[VIO_Z+1]]=0; index[xyzv[VIO_Z+1]]<3; index[xyzv[VIO_Z+1]]++) {
          SET_VOXEL(new_field, \
                    index[0], index[1], index[2], index[3], index[4], \
                    vector_val[ index[ xyzv[ VIO_Z+1] ] ]);
        }


      }
    }
    if (globals->flags.verbose>0)
      update_progress_report( &progress,index[xyzv[VIO_X]]+1);
  }
  if (globals->flags.verbose>0)
    terminate_progress_report( &progress );

                 /* delete and free up old data */
  delete_volume(non_lin_part->displacement_volume);
               /* set new volumes into transform */
  non_lin_part->displacement_volume = new_field;

}