Ejemplo n.º 1
0
void save_volume(VIO_Volume d, char *filename)
{
  VIO_Status status;

  status = output_volume(filename,NC_UNSPECIFIED, FALSE, 0.0, 0.0, d, (char *)NULL,
                         (minc_output_options *)NULL);

  if (status != OK)
    print_error_and_line_num("problems writing  volume `%s'.",__FILE__, __LINE__, filename);

}
Ejemplo n.º 2
0
VIO_Status gradient3D_volume(FILE *ifd, 
                                VIO_Volume data, 
                                int xyzv[VIO_MAX_DIMENSIONS],
                                char *infile,
                                char *outfile, 
                                int ndim,
                                char *history,
                                int curvature_flg)

{ 
  float 
    *fdata,                        /* floating point storage for blurred volume */
    *f_ptr,                        /* pointer to fdata */
    tmp,
    max_val, 
    min_val,
    
    *dat_vector,                /* temp storage of original row, col or slice vect. */
    *dat_vecto2,                /* storage of result of dat_vector*kern                 */
    *kern;                        /* convolution kernel                               */
  int                                
    total_voxels,                
    vector_size_data,                /* original size of row, col or slice vector        */
    array_size_pow2,                /* actual size of vector/kernel data used in FFT    */
                                /* routines - needs to be a power of two            */
    array_size;

  int   
    data_offset;                /* offset required to place original data (size n)  */
                                /*  into array (size m=2^n) so that data is centered*/

  register int 
    slice_limit,
    row,col,slice,                /* counters to access original data                 */
    vindex;                        /* counter to access vector and vecto2              */

  int 
    slice_size,                        /* size of each data step - in bytes                */
    row_size, col_size;
                

  char
    full_outfilename[256];        /* name of output file */

  progress_struct 
    progress;                        /* used to monitor progress of calculations         */

  VIO_Status 
    status;
  
  int
    sizes[3],                        /* number of rows, cols and slices */
    pos[3];                          /* Input order of rows, cols, slices */

  VIO_Real
    steps[3];                        /* size of voxel step from center to center in x,y,z */

  /*---------------------------------------------------------------------------------*/
  /*             start by setting up the raw data.                                   */
  /*---------------------------------------------------------------------------------*/



  get_volume_sizes(data, sizes);          /* rows,cols,slices */
  get_volume_separations(data, steps);
  
  slice_size = sizes[xyzv[VIO_Y]] * sizes[xyzv[VIO_X]];    /* sizeof one slice  */
  col_size   = sizes[xyzv[VIO_Y]];               /* sizeof one column */
  row_size   = sizes[xyzv[VIO_X]];               /* sizeof one row    */
  
  total_voxels = sizes[xyzv[VIO_Y]]*sizes[xyzv[VIO_X]]*sizes[xyzv[VIO_Z]];
  
  ALLOC(fdata, total_voxels);
  f_ptr = fdata;

         /* read in data of input file. */

  set_file_position(ifd,(long)0);
  status = io_binary_data(ifd,READ_FILE, fdata, sizeof(float), total_voxels);
  if (status != OK)
    print_error_and_line_num("problems reading binary data...\n",__FILE__, __LINE__);


  /*--------------------------------------------------------------------------------------*/
  /*                get ready to start up the transformation.                             */
  /*--------------------------------------------------------------------------------------*/
  
  initialize_progress_report( &progress, FALSE, sizes[xyzv[VIO_Z]] + sizes[xyzv[VIO_Y]] + sizes[xyzv[VIO_X]] + 1,
                             "Gradient volume" );


  /* note data is stored by rows (along x), then by cols (along y) then slices (along z) */
  

  /*--------------------------------------------------------------------------------------*/
  /*                start with rows - i.e. the d/dx volume                                */
  /*--------------------------------------------------------------------------------------*/
  
  /*-----------------------------------------------------------------------------*/
  /*             determine   size of data structures needed                      */
  
  vector_size_data = sizes[xyzv[VIO_X]]; 
  
  /*             array_size_pow2 will hold the size of the arrays for FFT convolution,
                 remember that ffts require arrays 2^n in length                          */
  
  array_size_pow2  = next_power_of_two(vector_size_data);
  array_size = 2*array_size_pow2+1;  /* allocate 2*, since each point is a    */
                                     /* complex number for FFT, and the plus 1*/
                                     /* is for the zero offset FFT routine    */

  ALLOC(dat_vector, array_size);
  ALLOC(dat_vecto2, array_size);
  ALLOC(kern      , array_size);
  
  /*    1st calculate kern array for FT of 1st derivitive */
  
  make_kernel_FT(kern,array_size_pow2, ABS(steps[xyzv[VIO_X]]));

  if (curvature_flg)                /* 2nd derivative kernel */
    muli_vects(kern,kern,kern,array_size_pow2);

  /*    calculate offset for original data to be placed in vector            */
  
  data_offset = (array_size_pow2-sizes[xyzv[VIO_X]])/2;
  
  max_val = -FLT_MAX;
  min_val =  FLT_MAX;


  /*    2nd now convolve this kernel with the rows of the dataset            */  
  
  slice_limit = 0;
  switch (ndim) {
  case 1: slice_limit = 0; break;
  case 2: slice_limit = sizes[xyzv[VIO_Z]]; break;
  case 3: slice_limit = sizes[xyzv[VIO_Z]]; break;
  }


  for (slice = 0; slice < slice_limit; slice++) {      /* for each slice */
    
    for (row = 0; row < sizes[xyzv[VIO_Y]]; row++) {           /* for each row   */
      
      f_ptr = fdata + slice*slice_size + row*sizes[xyzv[VIO_X]];
      memset(dat_vector,0,(2*array_size_pow2+1)*sizeof(float));
      
      for (col=0; col< sizes[xyzv[VIO_X]]; col++) {        /* extract the row */
        dat_vector[1 +2*(col+data_offset)  ] = *f_ptr++;
      }
      
      fft1(dat_vector,array_size_pow2,1);
      muli_vects(dat_vecto2,dat_vector,kern,array_size_pow2);
      fft1(dat_vecto2,array_size_pow2,-1);
      
      f_ptr = fdata + slice*slice_size + row*sizes[xyzv[VIO_X]];
      for (col=0; col< sizes[xyzv[VIO_X]]; col++) {        /* put the row back */
        
        vindex = 1 + 2*(col+data_offset);
       *f_ptr = dat_vecto2[vindex]/array_size_pow2;


        if (max_val<*f_ptr) max_val = *f_ptr;
        if (min_val>*f_ptr) min_val = *f_ptr;


        f_ptr++;
      }
      
      
    }
    update_progress_report( &progress, slice+1 );
  }
  
  FREE(dat_vector);
  FREE(dat_vecto2);
  FREE(kern      );
    

  f_ptr = fdata;

  set_volume_real_range(data, min_val, max_val);
  
  
  printf("Making byte volume dx..." );
  for(slice=0; slice<sizes[xyzv[VIO_Z]]; slice++) {
    pos[xyzv[VIO_Z]] = slice;
    for(row=0; row<sizes[xyzv[VIO_Y]]; row++) {
      pos[xyzv[VIO_Y]] = row;
      for(col=0; col<sizes[xyzv[VIO_X]]; col++) {
        pos[xyzv[VIO_X]] = col;
        tmp = CONVERT_VALUE_TO_VOXEL(data, *f_ptr);
        SET_VOXEL_3D( data, pos[0], pos[1], pos[2], tmp);
        f_ptr++;
      }
    }
  }


  if (!curvature_flg)
    sprintf(full_outfilename,"%s_dx.mnc",outfile);
  else
    sprintf(full_outfilename,"%s_dxx.mnc",outfile);

  if (debug)
    print ("dx: min = %f, max = %f\n",min_val, max_val);

  status = output_modified_volume(full_outfilename, NC_UNSPECIFIED, FALSE, 
                                  min_val, max_val, data, infile, history, NULL);

  if (status != OK)
    print_error_and_line_num("problems writing dx gradient data...\n",__FILE__, __LINE__);


  
  /*--------------------------------------------------------------------------------------*/
  /*                 now do cols - i.e. the d/dy volume                                   */
  /*--------------------------------------------------------------------------------------*/
  
  /*-----------------------------------------------------------------------------*/
  /*             determine   size of data structures needed                      */
  

  set_file_position(ifd,0);
  status = io_binary_data(ifd,READ_FILE, fdata, sizeof(float), total_voxels);
  if (status != OK)
    print_error_and_line_num("problems reading binary data...\n",__FILE__, __LINE__);




  
  f_ptr = fdata;

  vector_size_data = sizes[xyzv[VIO_Y]];
  
  /*             array_size_pow2 will hold the size of the arrays for FFT convolution,
                 remember that ffts require arrays 2^n in length                          */
  
  array_size_pow2  = next_power_of_two(vector_size_data);
  array_size = 2*array_size_pow2+1;  /* allocate 2*, since each point is a    */
                                     /* complex number for FFT, and the plus 1*/
                                     /* is for the zero offset FFT routine    */
  
  ALLOC(dat_vector, array_size);
  ALLOC(dat_vecto2, array_size);
  ALLOC(kern      , array_size);
  
  /*    1st calculate kern array for FT of 1st derivitive */
  
  make_kernel_FT(kern,array_size_pow2, ABS(steps[xyzv[VIO_Y]]));
  
  if (curvature_flg)                /* 2nd derivative kernel */
    muli_vects(kern,kern,kern,array_size_pow2);

  /*    calculate offset for original data to be placed in vector            */
  
  data_offset = (array_size_pow2-sizes[xyzv[VIO_Y]])/2;
  
  /*    2nd now convolve this kernel with the rows of the dataset            */
  
  max_val = -FLT_MAX;
  min_val =  FLT_MAX;

  switch (ndim) {
  case 1: slice_limit = 0; break;
  case 2: slice_limit = sizes[xyzv[VIO_Z]]; break;
  case 3: slice_limit = sizes[xyzv[VIO_Z]]; break;
  }

  for (slice = 0; slice < slice_limit; slice++) {      /* for each slice */
    
    for (col = 0; col < sizes[xyzv[VIO_X]]; col++) {           /* for each col   */
      
      /*         f_ptr = fdata + slice*slice_size + row*sizeof(float); */
      
      f_ptr = fdata + slice*slice_size + col;
      
      
      memset(dat_vector,0,(2*array_size_pow2+1)*sizeof(float));
      
      for (row=0; row< sizes[xyzv[VIO_Y]]; row++) {        /* extract the col */
        dat_vector[1 +2*(row+data_offset) ] = *f_ptr;
        f_ptr += row_size;
      }
      
      
      fft1(dat_vector,array_size_pow2,1);
      muli_vects(dat_vecto2,dat_vector,kern,array_size_pow2);
      fft1(dat_vecto2,array_size_pow2,-1);
      
      f_ptr = fdata + slice*slice_size + col;
      for (row=0; row< sizes[xyzv[VIO_Y]]; row++) {        /* put the col back */
        
        vindex = 1 + 2*(row+data_offset);
        
        *f_ptr = dat_vecto2[vindex]/array_size_pow2;
        
        if (max_val<*f_ptr) max_val = *f_ptr;
        if (min_val>*f_ptr) min_val = *f_ptr;

        f_ptr += row_size;
        
        
      }
      
    }
    update_progress_report( &progress, slice+sizes[xyzv[VIO_Z]]+1 );
    
  }
  
  FREE(dat_vector);
  FREE(dat_vecto2);
  FREE(kern      );
  
  f_ptr = fdata;
  
  set_volume_real_range(data, min_val, max_val);


  printf("Making byte volume dy..." );
  for(slice=0; slice<sizes[xyzv[VIO_Z]]; slice++) {
    pos[xyzv[VIO_Z]] = slice;
    for(row=0; row<sizes[xyzv[VIO_Y]]; row++) {
      pos[xyzv[VIO_Y]] = row;
      for(col=0; col<sizes[xyzv[VIO_X]]; col++) {
        pos[xyzv[VIO_X]] = col;
        tmp = CONVERT_VALUE_TO_VOXEL(data, *f_ptr);
        SET_VOXEL_3D( data, pos[0], pos[1], pos[2], tmp);
        f_ptr++;
      }
    }
  }

  if (!curvature_flg)
    sprintf(full_outfilename,"%s_dy.mnc",outfile);
  else
    sprintf(full_outfilename,"%s_dyy.mnc",outfile);


  if (debug)
    print ("dy: min = %f, max = %f\n",min_val, max_val);

  status = output_modified_volume(full_outfilename, NC_UNSPECIFIED, FALSE, 
                                  min_val, max_val, data, infile, history, NULL);
  if (status != OK)
    print_error_and_line_num("problems writing dy gradient data...",__FILE__, __LINE__);
  
  
  /*--------------------------------------------------------------------------------------*/
  /*                 now do slices - i.e. the d/dz volume                                 */
  /*--------------------------------------------------------------------------------------*/
  
  /*-----------------------------------------------------------------------------*/
  /*             determine   size of data structures needed                      */


  set_file_position(ifd,0);
  status = io_binary_data(ifd,READ_FILE, fdata, sizeof(float), total_voxels);
  if (status != OK)
    print_error_and_line_num("problems reading binary data...\n",__FILE__, __LINE__);
  f_ptr = fdata;
  
  vector_size_data = sizes[xyzv[VIO_Z]];

  /*             array_size_pow2 will hold the size of the arrays for FFT convolution,
                 remember that ffts require arrays 2^n in length                          */
  
  array_size_pow2  = next_power_of_two(vector_size_data);
  array_size = 2*array_size_pow2+1;  /* allocate 2*, since each point is a    */
                                     /* complex number for FFT, and the plus 1*/
                                     /* is for the zero offset FFT routine    */
  
  ALLOC(dat_vector, array_size);
  ALLOC(dat_vecto2, array_size);
  ALLOC(kern      , array_size);

  if (ndim==1 || ndim==3) {
    
    /*    1st calculate kern array for FT of 1st derivitive */
    
    make_kernel_FT(kern,array_size_pow2, ABS(steps[xyzv[VIO_Z]]));

    if (curvature_flg)                /* 2nd derivative kernel */
      muli_vects(kern,kern,kern,array_size_pow2);
    
    /*    calculate offset for original data to be placed in vector            */
    
    data_offset = (array_size_pow2-sizes[xyzv[VIO_Z]])/2;
    
    /*    2nd now convolve this kernel with the slices of the dataset            */
    
    max_val = -FLT_MAX;
    min_val =  FLT_MAX;
    
    
    for (col = 0; col < sizes[xyzv[VIO_X]]; col++) {      /* for each column */
      
      for (row = 0; row < sizes[xyzv[VIO_Y]]; row++) {           /* for each row   */
        
        f_ptr = fdata + col*col_size + row;
        
        memset(dat_vector,0,(2*array_size_pow2+1)*sizeof(float));
        
        for (slice=0; slice< sizes[xyzv[VIO_Z]]; slice++) {        /* extract the slice vector */
          dat_vector[1 +2*(slice+data_offset) ] = *f_ptr;
          f_ptr += slice_size;
        }
        
        fft1(dat_vector,array_size_pow2,1);
        muli_vects(dat_vecto2,dat_vector,kern,array_size_pow2);
        fft1(dat_vecto2,array_size_pow2,-1);
        
        f_ptr = fdata + col*col_size + row;
        
        for (slice=0; slice< sizes[xyzv[VIO_Z]]; slice++) {        /* put the vector back */
          
          vindex = 1 + 2*(slice+data_offset);
          
          *f_ptr = dat_vecto2[vindex]/array_size_pow2;
          
          if (max_val<*f_ptr) max_val = *f_ptr;
          if (min_val>*f_ptr) min_val = *f_ptr;
          
          f_ptr += slice_size;
        }
        
        
      }
      update_progress_report( &progress, col + 2*sizes[xyzv[VIO_Z]] + 1 );
      
    }
    
  }  /* if ndim */
  else {
    max_val = 0.00001;
    min_val = 0.00000;
    
    for (col = 0; col < sizes[xyzv[VIO_X]]; col++) {      /* for each column */
      for (row = 0; row < sizes[xyzv[VIO_Y]]; row++) {           /* for each row   */
        *f_ptr = 0.0;
        f_ptr++;
      }
    }
  }
  
  
  FREE(dat_vector);
  FREE(dat_vecto2);
  FREE(kern      );
  
  
/* set up the correct info to copy the data back out in mnc */

  f_ptr = fdata;
  
  set_volume_real_range(data, min_val, max_val);


  printf("Making byte volume dz..." );
  for(slice=0; slice<sizes[xyzv[VIO_Z]]; slice++) {
    pos[xyzv[VIO_Z]] = slice;
    for(row=0; row<sizes[xyzv[VIO_Y]]; row++) {
      pos[xyzv[VIO_Y]] = row;
      for(col=0; col<sizes[xyzv[VIO_X]]; col++) {
        pos[xyzv[VIO_X]] = col;
        tmp = CONVERT_VALUE_TO_VOXEL(data, *f_ptr);
        SET_VOXEL_3D( data, pos[0], pos[1], pos[2], tmp);
        f_ptr++;
      }
    }
  }

  if (!curvature_flg)
    sprintf(full_outfilename,"%s_dz.mnc",outfile);
  else
    sprintf(full_outfilename,"%s_dzz.mnc",outfile);


  if (debug)
    print ("dz: min = %f, max = %f\n",min_val, max_val);

  status = output_modified_volume(full_outfilename, NC_UNSPECIFIED, FALSE, 
                                  min_val, max_val, data, infile, history, NULL);

  if (status != OK)
    print_error_and_line_num("problems writing dz gradient data...",__FILE__, __LINE__);



  terminate_progress_report( &progress );

  FREE(fdata);

  return(status);
  
}
Ejemplo n.º 3
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);

  
}
Ejemplo n.º 4
0
float go_get_samples_with_offset(
    VIO_Volume data,                  /* The volume of data */
    VIO_Volume mask,                  /* The target mask */
    float *x, float *y, float *z,     /* the positions of the sub-lattice */
    VIO_Real  dx, VIO_Real  dy, VIO_Real dz,  /* the local displacement to apply  */
    int obj_func,                     /* the type of obj function req'd   */
    int len,                          /* number of sub-lattice nodes      */
    int *sample_target_count,         /* number of nonmasked  sub-lattice nodes */
    float normalization,              /* normalization factor for obj func*/
    float *a1,                        /* feature value for (x,y,z) nodes  */
    VIO_BOOL *m1,                     /* mask flag for (x,y,z) nodes in source */
    VIO_BOOL use_nearest_neighbour)   /* interpolation flag              */
{
    double
    sample, r,
            s1,s2,s3,s4,s5,tmp;                   /* accumulators for inner loop */
    int
    sizes[3],
          ind0, ind1, ind2,
          offset0, offset1, offset2,
          c,number_of_nonzero_samples;
    int xs,ys,zs;
    float
    f_trans, f_scale;

    static double v0, v1, v2;
    static double f0, f1, f2, r0, r1, r2, r1r2, r1f2, f1r2, f1f2;
    static double v000, v001, v010, v011, v100, v101, v110, v111;

    double ***double_ptr;

    double mean_s = 0.0;		/* init variables for stats */
    double mean_t = 0.0;
    double var_s = 0.0;
    double var_t = 0.0;
    double covariance = 0.0;

    number_of_nonzero_samples = 0;

    get_volume_sizes(data, sizes);
    xs = sizes[0];
    ys = sizes[1];
    zs = sizes[2];


    s1 = s2 = s3 = s4 = s5 = 0.0;
    ++a1;
    ++m1;                   /* inc pointer, so that we are pointing to
                                   the first feature value, corresponding
                                   to the first sub-lattice point x,y,z   */



    if (use_nearest_neighbour) {
        /* then do fast NN interpolation */

        dx += 0.;                        /* to achieve `rounding' for ind0, ind1 and */
        dy += 0.;                        /* ind2 below */
        dz += 0.;

        double_ptr = VOXEL_DATA (data);

        /* increment by one as we index from 1...n (but the array is ALLOC'd from 0..n) */
        x++;
        y++;
        z++;

        /* for each sub-lattice node */
        for(c=len; c--;) {

            /*
             *  this is code to test timing of David's evaluate_volume_in_world()
             *  interpolation code.  While it is _VERY_ general, the eval_vol_in_world()'s
             *  NN interpolation is approximately 8-9 times slower than the bit of
             *  fast NN code below.
             *
             *  VIO_Real sampleR, index[5], wx, wy, wz;
             *  index[0] = (VIO_Real) ( *x + dx );
             *  index[1] = (VIO_Real) ( *y + dy );
             *  index[2] = (VIO_Real) ( *z + dz );
             *  index[3] = index[4] = 0.0;
             *  convert_voxel_to_world(data, index, &wx, &wy, &wz );
             *  evaluate_volume_in_world(data, wx, wy, wz,
             *                            0, TRUE, 0.0, &sampleR,
             *                            NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
             *   sample = (double)sampleR;
             */

            if (!(*m1) && (voxel_point_not_masked(mask, (VIO_Real)*x, (VIO_Real)*y, (VIO_Real)*z)) && (!(obj_func==NONLIN_CHAMFER) ||  (*a1>0)) ) {

                ind0 = (int) ( *x + dx );
                ind1 = (int) ( *y + dy );
                ind2 = (int) ( *z + dz );

                if (ind0>=0 && ind0<xs &&
                        ind1>=0 && ind1<ys &&
                        ind2>=0 && ind2<zs) {
                    sample = (double)(double_ptr[ind0][ind1][ind2]);
                }
                else {
                    sample = 0.0;
                }

#include "switch_obj_func.c"	/* contains a case statement to do the sample-to-sample computations required for each possible non-lin objective function */
            }

            /* increment the coordinate, value and mask array pointers */
            x++;			/* x,y,z are the coords of the sublattice in the fixed (source) image */
            y++;
            z++;
            a1++;			/* a1 is from the fixed image */
            m1++;			/* m1 is rom the mask on the fixed image */

        }
    }
    else {                        /* then do fast trilinear interpolation */

        /* set up offsets */
        offset0 = (Gglobals->count[VIO_Z] > 1) ? 1 : 0;
        offset1 = (Gglobals->count[VIO_Y] > 1) ? 1 : 0;
        offset2 = (Gglobals->count[VIO_X] > 1) ? 1 : 0;

        double_ptr = VOXEL_DATA (data);

        /* increment by one as we index from 1...n */
        ++x;
        ++y;
        ++z;

        /* for each sub-lattice node */
        for(c=len; c--;) {

            /*  fast tri-linear interplation */

            if  (  !(*m1) && (voxel_point_not_masked(mask, (VIO_Real)*x, (VIO_Real)*y, (VIO_Real)*z)) && (!(obj_func==NONLIN_CHAMFER) ||  (*a1>0)) ) {
                v0 = (VIO_Real) ( *x + dx );
                v1 = (VIO_Real) ( *y + dy );
                v2 = (VIO_Real) ( *z + dz );

                ind0 = (int)v0;
                ind1 = (int)v1;
                ind2 = (int)v2;

                if (ind0>=0 && ind0<(xs-offset0) &&
                        ind1>=0 && ind1<(ys-offset1) &&
                        ind2>=0 && ind2<(zs-offset2)) {

                    /* get the data */
                    v000 = (VIO_Real)(double_ptr[ind0        ][ind1        ][ind2        ]);
                    v001 = (VIO_Real)(double_ptr[ind0        ][ind1        ][ind2+offset2]);
                    v010 = (VIO_Real)(double_ptr[ind0        ][ind1+offset1][ind2        ]);
                    v011 = (VIO_Real)(double_ptr[ind0        ][ind1+offset1][ind2+offset2]);
                    v100 = (VIO_Real)(double_ptr[ind0+offset0][ind1        ][ind2        ]);
                    v101 = (VIO_Real)(double_ptr[ind0+offset0][ind1        ][ind2+offset2]);
                    v110 = (VIO_Real)(double_ptr[ind0+offset0][ind1+offset1][ind2        ]);
                    v111 = (VIO_Real)(double_ptr[ind0+offset0][ind1+offset1][ind2+offset2]);

                    /* Get the fraction parts */
                    f0 = v0 - ind0;
                    f1 = v1 - ind1;
                    f2 = v2 - ind2;
                    r0 = 1.0 - f0;
                    r1 = 1.0 - f1;
                    r2 = 1.0 - f2;

                    /* Do the interpolation */
                    r1r2 = r1 * r2;
                    r1f2 = r1 * f2;
                    f1r2 = f1 * r2;
                    f1f2 = f1 * f2;

                    sample   =
                        r0 *  (r1r2 * v000 +
                               r1f2 * v001 +
                               f1r2 * v010 +
                               f1f2 * v011);
                    sample  +=
                        f0 *  (r1r2 * v100 +
                               r1f2 * v101 +
                               f1r2 * v110 +
                               f1f2 * v111);

                    sample = sample;


                }
                else {
                    sample = 0.0;
                }


#include "switch_obj_func.c"

            }

            /* increment the coordinate, value and mask array pointers */
            x++;			/* x,y,z are the coords of the sublattice in the fixed (source) image */
            y++;
            z++;
            a1++;			/* a1 is from the fixed image */
            m1++;			/* m1 is rom the mask on the fixed image */

        }



        /* do the last bits of the similarity function
           calculation here - normalizing each obj_func
           where-ever possible: */
        r = 0.0;

        switch (obj_func) {

        case NONLIN_XCORR:            /* use standard normalized cross-correlation
                                   where 0.0 < r < 1.0, where 1.0 is best*/
            if ( normalization < 0.001 && s3 < 0.00001) {
                r = 1.0;
            }
            else {
                if ( normalization < 0.001 || s3 < 0.00001) {
                    r = 0.0;
                }
                else {
                    r = s1 / ((sqrt((double)s2))*(sqrt((double)s3)));
                }
            }
            /* r = 1.0 - r;                 now, 0 is best                   */
            break;

        case NONLIN_DIFF:             /* normalization stores the number of samples in
                                   the sub-lattice
                                   s1 stores the sum of the magnitude of
                                   the differences*/

            r = -s1 /number_of_nonzero_samples;        /* r = average intensity difference ; with
                                   -max(intensity range) < r < 0,
                                   where 0 is best                  */
            break;
        case NONLIN_LABEL:
            r = s1 /number_of_nonzero_samples;           /* r = average label agreement,
                                    s1 stores the number of similar labels
                                   0 < r < 1.0
                                   where 1.0 is best                */
            break;
        case NONLIN_CHAMFER:
            if (number_of_nonzero_samples>0) {
                r = 1.0 - (s1 / (20.0*number_of_nonzero_samples));
                /* r = 1- average distance / 20mm
                       0 < r < ~1.0
                   where 1.0 is best
                       and where 2.0cm is an arbitrary value to
                       norm the dist, corresponding to a guess
                       at the maximum average cortical variability

                       so the max(r) could be greater than
                       1.0, but when it is, shouldn't
                       chamfer have larger weight to drive
                       the fit? */
            }
            else
                r = 2.0;                 /* this is simply a value > 1.5, used as a
                                   flag to indicate that there were no
                                   samples used for the chamfer */
            break;
        case NONLIN_CORRCOEFF:
        {
            /* Accumulators:
             * s1 = sum of source image values
             * s2 = sum of target image values
             * s3 = sum of squared source image values
             * s4 = sum of squared target image values
             * s5 = sum of source*target values
             *
             * normalization = #values considered
             */
            if (number_of_nonzero_samples>0) {
                mean_s = s1 / number_of_nonzero_samples;
                mean_t = s2 / number_of_nonzero_samples;
                var_s = s3 / number_of_nonzero_samples - mean_s*mean_s;
                var_t = s4 / number_of_nonzero_samples - mean_t*mean_t;
                covariance = s5 / number_of_nonzero_samples - mean_s*mean_t;
            }
            else {
                mean_s = 0.0;
                mean_t = 0.0;
                var_s = 0.0;
                var_t = 0.0;
                covariance = 0.0;
            }


            if ((var_s < 0.00001) || (var_t < 0.00001) ) {
                r = 0.0;
            }
            else {
                r = covariance / sqrt( var_s*var_t );
            }
        }
        break;

        case NONLIN_SQDIFF:           /* normalization stores the number of samples
                                   in the sub-lattice.
                                   s1 stores the sum of the squared intensity
                                   differences */
            r = -s1 /number_of_nonzero_samples;
            break;

        default:
            print_error_and_line_num("Objective function %d not supported in go_get_samples_with_offset",__FILE__, __LINE__,obj_func);
        }


        return(r);
    }

}
Ejemplo n.º 5
0
void interpolate_deformation_slice(VIO_Volume volume, 
                                          VIO_Real wx,Real wy,Real wz,
                                          VIO_Real def[])
{
  VIO_Real
    world[VIO_N_DIMENSIONS],
    v00,v01,v02,v03, 
    v10,v11,v12,v13, 
    v20,v21,v22,v23, 
    v30,v31,v32,v33;
  long 
    ind0, ind1, ind2;
  VIO_Real
    voxel[VIO_MAX_DIMENSIONS],
    frac[VIO_MAX_DIMENSIONS];
  int 
    i,
    xyzv[VIO_MAX_DIMENSIONS],
    sizes[VIO_MAX_DIMENSIONS];
  double temp_result;
  
  
  def[VIO_X] = def[VIO_Y] = def[VIO_Z] = 0.0;
  world[VIO_X] = wx; world[VIO_Y] = wy; world[VIO_Z] = wz;
  convert_world_to_voxel(volume, wx, wy, wz, voxel);
  
  /* Check that the coordinate is inside the volume */
  
  get_volume_sizes(volume, sizes);
  get_volume_XYZV_indices(volume, xyzv);

  if ((voxel[ xyzv[VIO_X] ] < 0) || (voxel[ xyzv[VIO_X] ] >=sizes[ xyzv[VIO_X]]) ||
      (voxel[ xyzv[VIO_Y] ] < 0) || (voxel[ xyzv[VIO_Y] ] >=sizes[ xyzv[VIO_Y]]) ||
      (voxel[ xyzv[VIO_Z] ] < 0) || (voxel[ xyzv[VIO_Z] ] >=sizes[ xyzv[VIO_Z]]))  {
    return ;
  }
  
  if (/*(sizes[ xyzv[VIO_Z] ] == 1) &&*/ xyzv[VIO_Z]==1) {
    
    /* Get the whole and fractional part of the coordinate */
    ind0 = FLOOR( voxel[ xyzv[VIO_Z] ] );
    ind1 = FLOOR( voxel[ xyzv[VIO_Y] ] );
    ind2 = FLOOR( voxel[ xyzv[VIO_X] ] );
    frac[VIO_Y] = voxel[ xyzv[VIO_Y] ] - ind1;
    frac[VIO_X] = voxel[ xyzv[VIO_X] ] - ind2;
    
    if (sizes[xyzv[VIO_X]] < 4 || sizes[xyzv[VIO_Y]] < 4) {
      def[VIO_X] = get_volume_real_value(volume, 0, ind0, ind1, ind2, 0);
      def[VIO_Y] = get_volume_real_value(volume, 1, ind0, ind1, ind2, 0);
      def[VIO_Z] = get_volume_real_value(volume, 2, ind0, ind1, ind2, 0);
      return;
    }

    if (ind1==0) 
      frac[VIO_Y] -= 1.0;
    else {
      ind1--;
      while ( ind1+3 >= sizes[xyzv[VIO_Y]] ) {
        ind1--;
        frac[VIO_Y] += 1.0;
      }
    }
    if (ind2==0) 
      frac[VIO_X] -= 1.0;
    else {
      ind2--;
      while ( ind2+3 >= sizes[xyzv[VIO_X]] ) {
        ind2--;
        frac[VIO_X] += 1.0;
      }
    }
    for(i=0; i<3; i++) {
      GET_VOXEL_4D(v00, volume, i, ind0, ind1, ind2);
      GET_VOXEL_4D(v01, volume, i, ind0, ind1, ind2+1);
      GET_VOXEL_4D(v02, volume, i, ind0, ind1, ind2+2);
      GET_VOXEL_4D(v03, volume, i, ind0, ind1, ind2+3);
      
      GET_VOXEL_4D(v10, volume, i, ind0, ind1+1, ind2);
      GET_VOXEL_4D(v11, volume, i, ind0, ind1+1, ind2+1);
      GET_VOXEL_4D(v12, volume, i, ind0, ind1+1, ind2+2);
      GET_VOXEL_4D(v13, volume, i, ind0, ind1+1, ind2+3);
      
      GET_VOXEL_4D(v20, volume, i, ind0, ind1+2, ind2);
      GET_VOXEL_4D(v21, volume, i, ind0, ind1+2, ind2+1);
      GET_VOXEL_4D(v22, volume, i, ind0, ind1+2, ind2+2);
      GET_VOXEL_4D(v23, volume, i, ind0, ind1+2, ind2+3);
      
      GET_VOXEL_4D(v30, volume, i, ind0, ind1+3, ind2);
      GET_VOXEL_4D(v31, volume, i, ind0, ind1+3, ind2+1);
      GET_VOXEL_4D(v32, volume, i, ind0, ind1+3, ind2+2);
      GET_VOXEL_4D(v33, volume, i, ind0, ind1+3, ind2+3);
      
      CUBIC_BIVAR(v00,v01,v02,v03, \
                  v10,v11,v12,v13, \
                  v20,v21,v22,v23, \
                  v30,v31,v32,v33, \
                  frac[VIO_Y],frac[VIO_X], temp_result);
      def[i] = CONVERT_VOXEL_TO_VALUE(volume,temp_result);
    }
    
    

  }
  else {
    print ("\n\nxyzv[] = %d %d %d %d\n",xyzv[0],xyzv[1],xyzv[2],xyzv[3]);
    print ("\n\nsizes[]= %d %d %d %d\n",sizes[0],sizes[1],sizes[2],sizes[3]);
    print_error_and_line_num("error in slice_interpolate", __FILE__, __LINE__);
  }

}
Ejemplo n.º 6
0
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;

}