Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

labels.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 00013 ---------------------------------------------------------------------------- */ 00014 00015 #include <volume_io/internal_volume_io.h> 00016 #include <bicpl/vols.h> 00017 00018 #ifndef lint 00019 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Volumes/labels.c,v 1.40 2000/02/06 15:30:55 stever Exp $"; 00020 #endif 00021 00022 /* ----------------------------- MNI Header ----------------------------------- 00023 @NAME : set_label_volume_real_range 00024 @INPUT : volume 00025 @OUTPUT : 00026 @RETURNS : 00027 @DESCRIPTION: Sets the real range to be equal to the voxel range. 00028 @METHOD : 00029 @GLOBALS : 00030 @CALLS : 00031 @CREATED : 1993 David MacDonald 00032 @MODIFIED : 00033 ---------------------------------------------------------------------------- */ 00034 00035 public void set_label_volume_real_range( 00036 Volume volume ) 00037 { 00038 if( get_volume_data_type(volume) != FLOAT && 00039 get_volume_data_type(volume) != DOUBLE ) 00040 { 00041 set_volume_real_range( volume, 00042 get_volume_voxel_min(volume), 00043 get_volume_voxel_max(volume) ); 00044 } 00045 else 00046 volume->real_range_set = FALSE; 00047 } 00048 00049 /* ----------------------------- MNI Header ----------------------------------- 00050 @NAME : create_label_volume 00051 @INPUT : volume 00052 type 00053 @OUTPUT : 00054 @RETURNS : a volume 00055 @DESCRIPTION: Creates a label volume with the same tessellation as the volume. 00056 @METHOD : 00057 @GLOBALS : 00058 @CALLS : 00059 @CREATED : 1993 David MacDonald 00060 @MODIFIED : 00061 ---------------------------------------------------------------------------- */ 00062 00063 public Volume create_label_volume( 00064 Volume volume, 00065 nc_type type ) 00066 { 00067 Volume label_volume; 00068 00069 if( type == NC_UNSPECIFIED ) 00070 type = NC_BYTE; 00071 00072 label_volume = copy_volume_definition_no_alloc( volume, type, FALSE, 00073 0.0, -1.0 ); 00074 00075 set_label_volume_real_range( label_volume ); 00076 00077 return( label_volume ); 00078 } 00079 00080 /* ----------------------------- MNI Header ----------------------------------- 00081 @NAME : check_alloc_label_data 00082 @INPUT : volume 00083 @OUTPUT : 00084 @RETURNS : 00085 @DESCRIPTION: Checks if the label data has been allocated. 00086 @METHOD : 00087 @GLOBALS : 00088 @CALLS : 00089 @CREATED : 1993 David MacDonald 00090 @MODIFIED : 00091 ---------------------------------------------------------------------------- */ 00092 00093 private void check_alloc_label_data( 00094 Volume volume ) 00095 { 00096 if( !volume_is_alloced( volume ) && !volume_is_cached(volume) ) 00097 { 00098 alloc_volume_data( volume ); 00099 set_all_volume_label_data( volume, 0 ); 00100 } 00101 } 00102 00103 public BOOLEAN is_label_volume_initialized( 00104 Volume volume ) 00105 { 00106 return( volume != NULL && 00107 ((volume->is_cached_volume && 00108 cached_volume_has_been_modified( &volume->cache )) || 00109 (!volume->is_cached_volume && 00110 multidim_array_is_alloced( &volume->array ))) ); 00111 } 00112 00113 /* ----------------------------- MNI Header ----------------------------------- 00114 @NAME : set_all_volume_label_data 00115 @INPUT : volume 00116 value 00117 @OUTPUT : 00118 @RETURNS : 00119 @DESCRIPTION: Sets the label value of all voxels to the value specified. 00120 @CREATED : Mar 1993 David MacDonald 00121 @MODIFIED : 00122 ---------------------------------------------------------------------------- */ 00123 00124 public void set_all_volume_label_data( 00125 Volume volume, 00126 int value ) 00127 { 00128 Data_types type; 00129 void *ptr; 00130 Real real_value; 00131 int v0, v1, v2, v3, v4; 00132 unsigned int n_voxels; 00133 00134 check_alloc_label_data( volume ); 00135 00136 type = get_volume_data_type( volume ); 00137 if( !volume->is_cached_volume && value == 0 && 00138 type != FLOAT && type != DOUBLE ) 00139 { 00140 GET_VOXEL_PTR( ptr, volume, 0, 0, 0, 0, 0 ); 00141 n_voxels = get_volume_total_n_voxels( volume ); 00142 (void)memset( ptr, 0, (size_t) n_voxels * (size_t) get_type_size(type)); 00143 } 00144 else 00145 { 00146 real_value = (Real) value; 00147 BEGIN_ALL_VOXELS( volume, v0, v1, v2, v3, v4 ) 00148 00149 set_volume_real_value( volume, v0, v1, v2, v3, v4, real_value ); 00150 00151 END_ALL_VOXELS 00152 } 00153 } 00154 00155 /* ----------------------------- MNI Header ----------------------------------- 00156 @NAME : set_volume_label_data 00157 @INPUT : volume 00158 x 00159 y 00160 z 00161 value 00162 @OUTPUT : 00163 @RETURNS : 00164 @DESCRIPTION: Sets the label data of the given voxel to the value. 00165 @CREATED : Mar 1993 David MacDonald 00166 @MODIFIED : 00167 ---------------------------------------------------------------------------- */ 00168 00169 public void set_volume_label_data_5d( 00170 Volume volume, 00171 int v0, 00172 int v1, 00173 int v2, 00174 int v3, 00175 int v4, 00176 int value ) 00177 { 00178 check_alloc_label_data( volume ); 00179 00180 set_volume_real_value( volume, v0, v1, v2, v3, v4, (Real) value ); 00181 } 00182 00183 public void set_volume_label_data( 00184 Volume volume, 00185 int voxel[], 00186 int value ) 00187 { 00188 set_volume_label_data_5d( volume, 00189 voxel[0], voxel[1], voxel[2], voxel[3], voxel[4], 00190 value ); 00191 } 00192 00193 /* ----------------------------- MNI Header ----------------------------------- 00194 @NAME : get_volume_label_data 00195 @INPUT : volume 00196 x 00197 y 00198 z 00199 @OUTPUT : 00200 @RETURNS : value 00201 @DESCRIPTION: Returns the label data of the given voxel. 00202 @CREATED : Mar 1993 David MacDonald 00203 @MODIFIED : 00204 ---------------------------------------------------------------------------- */ 00205 00206 public int get_volume_label_data( 00207 Volume volume, 00208 int voxel[] ) 00209 { 00210 return( get_volume_label_data_5d( volume, 00211 voxel[0], voxel[1], voxel[2], voxel[3], voxel[4] ) ); 00212 } 00213 00214 public int get_volume_label_data_5d( 00215 Volume volume, 00216 int v0, 00217 int v1, 00218 int v2, 00219 int v3, 00220 int v4 ) 00221 { 00222 int label; 00223 00224 if( volume == (Volume) NULL || !volume_is_alloced( volume ) ) 00225 return( 0 ); 00226 else 00227 { 00228 label = (int) get_volume_real_value( volume, v0, v1, v2, v3, v4 ); 00229 return( label ); 00230 } 00231 } 00232 00233 /* ----------------------------- MNI Header ----------------------------------- 00234 @NAME : get_3D_volume_label_data 00235 @INPUT : volume 00236 x 00237 y 00238 z 00239 @OUTPUT : 00240 @RETURNS : label 00241 @DESCRIPTION: Gets the label value of a 3D label volume. 00242 @METHOD : 00243 @GLOBALS : 00244 @CALLS : 00245 @CREATED : 1993 David MacDonald 00246 @MODIFIED : 00247 ---------------------------------------------------------------------------- */ 00248 00249 public int get_3D_volume_label_data( 00250 Volume volume, 00251 int x, 00252 int y, 00253 int z ) 00254 { 00255 int label; 00256 00257 if( volume == (Volume) NULL || !volume_is_alloced( volume ) ) 00258 return( 0 ); 00259 else 00260 { 00261 label = (int) get_volume_real_value( volume, x, y, z, 0, 0 ); 00262 return( label ); 00263 } 00264 } 00265 00266 /* ----------------------------- MNI Header ----------------------------------- 00267 @NAME : get_voxel_label_bit 00268 @INPUT : volume 00269 voxel 00270 bit 00271 @OUTPUT : 00272 @RETURNS : TRUE or FALSE 00273 @DESCRIPTION: Returns the label bit. 00274 @METHOD : 00275 @GLOBALS : 00276 @CALLS : 00277 @CREATED : 1993 David MacDonald 00278 @MODIFIED : 00279 ---------------------------------------------------------------------------- */ 00280 00281 public BOOLEAN get_voxel_label_bit( 00282 Volume volume, 00283 int voxel[], 00284 int bit ) 00285 { 00286 return( (get_volume_label_data( volume, voxel ) & bit) == 0 ); 00287 } 00288 00289 /* ----------------------------- MNI Header ----------------------------------- 00290 @NAME : set_voxel_label_bit 00291 @INPUT : volume 00292 voxel 00293 bit 00294 value 00295 @OUTPUT : 00296 @RETURNS : 00297 @DESCRIPTION: Sets the voxel label bit. 00298 @METHOD : 00299 @GLOBALS : 00300 @CALLS : 00301 @CREATED : 1993 David MacDonald 00302 @MODIFIED : 00303 ---------------------------------------------------------------------------- */ 00304 00305 public void set_voxel_label_bit( 00306 Volume volume, 00307 int voxel[], 00308 int bit, 00309 BOOLEAN value ) 00310 { 00311 int i, n_dims, v[MAX_DIMENSIONS], label, anded, new_label; 00312 00313 check_alloc_label_data( volume ); 00314 00315 n_dims = get_volume_n_dimensions(volume); 00316 00317 for_less( i, 0, n_dims ) 00318 v[i] = voxel[i]; 00319 00320 label = (int) get_volume_real_value( volume, v[0], v[1], v[2], v[3], v[4]); 00321 00322 anded = (label & bit); 00323 00324 if( value ) 00325 { 00326 if( anded != bit ) 00327 { 00328 new_label = label | bit; 00329 set_volume_real_value( volume, v[0], v[1], v[2], v[3], v[4], 00330 (Real) new_label ); 00331 } 00332 } 00333 else if( anded != 0 ) 00334 { 00335 new_label = label & (~bit); 00336 set_volume_real_value( volume, v[0], v[1], v[2], v[3], v[4], 00337 (Real) new_label ); 00338 } 00339 } 00340 00341 /* ----------------------------- MNI Header ----------------------------------- 00342 @NAME : set_all_volume_label_data_bit 00343 @INPUT : volume 00344 bit 00345 value - ON or OFF 00346 @OUTPUT : 00347 @RETURNS : 00348 @DESCRIPTION: Sets just the given bit of all the voxels' label data to the 00349 given value. 00350 @CREATED : Mar 1993 David MacDonald 00351 @MODIFIED : 00352 ---------------------------------------------------------------------------- */ 00353 00354 public void set_all_volume_label_data_bit( 00355 Volume volume, 00356 int bit, 00357 BOOLEAN value ) 00358 { 00359 int v[MAX_DIMENSIONS]; 00360 00361 check_alloc_label_data( volume ); 00362 00363 BEGIN_ALL_VOXELS( volume, v[0], v[1], v[2], v[3], v[4] ) 00364 00365 set_voxel_label_bit( volume, v, bit, value ); 00366 00367 END_ALL_VOXELS 00368 } 00369 00370 /* ----------------------------- MNI Header ----------------------------------- 00371 @NAME : get_volume_voxel_activity 00372 @INPUT : volume 00373 voxel 00374 activity_if_mixed 00375 @OUTPUT : 00376 @RETURNS : TRUE or FALSE 00377 @DESCRIPTION: Returns the voxel activity, by looking at the 2^d corners of the 00378 voxel. 00379 @METHOD : 00380 @GLOBALS : 00381 @CALLS : 00382 @CREATED : 1993 David MacDonald 00383 @MODIFIED : 00384 ---------------------------------------------------------------------------- */ 00385 00386 public BOOLEAN get_volume_voxel_activity( 00387 Volume volume, 00388 Real voxel[], 00389 BOOLEAN activity_if_mixed ) 00390 { 00391 BOOLEAN active_found, inactive_found; 00392 int c, int_index[MAX_DIMENSIONS], ind[MAX_DIMENSIONS]; 00393 int n[MAX_DIMENSIONS], sizes[MAX_DIMENSIONS]; 00394 00395 if( volume == (Volume) NULL || !volume_is_alloced( volume ) ) 00396 return( TRUE ); 00397 00398 get_volume_sizes( volume, sizes ); 00399 00400 for_less( c, 0, get_volume_n_dimensions(volume) ) 00401 if( voxel[c] < 0.0 || voxel[c] > (Real) sizes[c]-1.0 ) 00402 return( FALSE ); 00403 00404 for_less( c, 0, get_volume_n_dimensions(volume) ) 00405 { 00406 int_index[c] = (int) voxel[c]; 00407 if( int_index[c] == sizes[c] - 1 ) 00408 int_index[c] = sizes[c] - 2; 00409 n[c] = 2; 00410 } 00411 00412 for_less( c, get_volume_n_dimensions(volume), MAX_DIMENSIONS ) 00413 { 00414 n[c] = 1; 00415 int_index[c] = 0; 00416 } 00417 00418 active_found = FALSE; 00419 inactive_found = FALSE; 00420 00421 for_less( ind[X], int_index[X], int_index[X] + n[X] ) 00422 for_less( ind[Y], int_index[Y], int_index[Y] + n[Y] ) 00423 for_less( ind[Z], int_index[Z], int_index[Z] + n[Z] ) 00424 for_less( ind[3], int_index[3], int_index[3] + n[3] ) 00425 for_less( ind[4], int_index[4], int_index[4] + n[4] ) 00426 { 00427 if( get_volume_label_data( volume, ind ) == 0 ) 00428 { 00429 if( inactive_found ) 00430 return( activity_if_mixed ); 00431 active_found = TRUE; 00432 } 00433 else 00434 { 00435 if( active_found ) 00436 return( activity_if_mixed ); 00437 inactive_found = TRUE; 00438 } 00439 } 00440 00441 if( active_found && !inactive_found ) 00442 return( TRUE ); 00443 else if( !active_found && inactive_found ) 00444 return( FALSE ); 00445 else 00446 return( activity_if_mixed ); 00447 } 00448 00449 /* ----------------------------- MNI Header ----------------------------------- 00450 @NAME : get_input_volume_label_limits 00451 @INPUT : volume1 00452 volume2 00453 slice 00454 @OUTPUT : limits 00455 @RETURNS : 00456 @DESCRIPTION: Computes the range of overlap of volume2 in volume1. 00457 @METHOD : 00458 @GLOBALS : 00459 @CALLS : 00460 @CREATED : Aug. 1, 1995 David MacDonald 00461 @MODIFIED : May. 6, 1997 D. MacDonald - one slice of 3d volume 00462 ---------------------------------------------------------------------------- */ 00463 00464 private void get_input_volume_label_limits( 00465 Volume volume1, 00466 Volume volume2, 00467 int slice, 00468 int limits[2][N_DIMENSIONS] ) 00469 { 00470 int sizes1[N_DIMENSIONS], sizes2[N_DIMENSIONS]; 00471 int d, t[N_DIMENSIONS]; 00472 Real voxel1[N_DIMENSIONS], voxel2[N_DIMENSIONS]; 00473 int pos; 00474 Real xw, yw, zw; 00475 BOOLEAN first; 00476 00477 get_volume_sizes( volume1, sizes1 ); 00478 get_volume_sizes( volume2, sizes2 ); 00479 00480 first = TRUE; 00481 00482 for_less( t[0], 0, 2 ) 00483 for_less( t[1], 0, 2 ) 00484 for_less( t[2], 0, 2 ) 00485 { 00486 voxel2[0] = (Real) slice - 0.5 + (Real) t[0]; 00487 voxel2[1] = -0.5 + (Real) t[1] * (Real) sizes2[1]; 00488 voxel2[2] = -0.5 + (Real) t[2] * (Real) sizes2[2]; 00489 00490 convert_voxel_to_world( volume2, voxel2, &xw, &yw, &zw ); 00491 convert_world_to_voxel( volume1, xw, yw, zw, voxel1 ); 00492 00493 for_less( d, 0, N_DIMENSIONS ) 00494 { 00495 pos = FLOOR( voxel1[d] + 0.5 ); 00496 00497 if( first ) 00498 { 00499 limits[0][d] = pos; 00500 limits[1][d] = pos; 00501 } 00502 else 00503 { 00504 if( pos < limits[0][d] ) 00505 limits[0][d] = pos; 00506 else if( pos > limits[1][d] ) 00507 limits[1][d] = pos; 00508 } 00509 } 00510 00511 first = FALSE; 00512 } 00513 00514 for_less( d, 0, N_DIMENSIONS ) 00515 { 00516 if( limits[0][d] < 0 ) 00517 limits[0][d] = 0; 00518 if( limits[1][d] >= sizes1[d] ) 00519 limits[1][d] = sizes1[d] - 1; 00520 } 00521 } 00522 00523 /* ----------------------------- MNI Header ----------------------------------- 00524 @NAME : load_label_volume 00525 @INPUT : Filename 00526 @OUTPUT : label_volume 00527 @RETURNS : ERROR or OK 00528 @DESCRIPTION: Loads the label volume. 00529 @METHOD : 00530 @GLOBALS : 00531 @CALLS : 00532 @CREATED : 1993 David MacDonald 00533 @MODIFIED : Aug. 1, 1995 D. MacDonald - loaded volume no longer needs 00534 to be same grid. 00535 @MODIFIED : May. 6, 1997 D. MacDonald - now loads one slice at a time, 00536 and does not overwrite labels 00537 with 0's. 00538 @MODIFIED : Jun. 6, 1997 D. MacDonald - special case, fast, for matching 00539 coordinate systems 00540 ---------------------------------------------------------------------------- */ 00541 00542 public Status load_label_volume( 00543 STRING filename, 00544 Volume label_volume ) 00545 { 00546 int slice, n_slices; 00547 int label_voxel[N_DIMENSIONS]; 00548 int int_voxel[N_DIMENSIONS], int_file_value; 00549 int limits[2][N_DIMENSIONS]; 00550 int file_sizes[N_DIMENSIONS]; 00551 Real file_value, xw, yw, zw, amount_done; 00552 int int_y_voxel[N_DIMENSIONS]; 00553 Real y_voxel[N_DIMENSIONS]; 00554 Real voxel[N_DIMENSIONS], z_dx, z_dy, z_dz; 00555 Real y_dx, y_dy, y_dz; 00556 int int_z_dx, int_z_dy, int_z_dz; 00557 int int_y_dx, int_y_dy, int_y_dz; 00558 Real start_voxel[N_DIMENSIONS]; 00559 Real end_voxel[N_DIMENSIONS]; 00560 Volume file_volume, file_volume_3d; 00561 Minc_file file; 00562 BOOLEAN is_linear, is_integer_step; 00563 progress_struct progress; 00564 00565 check_alloc_label_data( label_volume ); 00566 00567 /*--- get 3d transformation in file */ 00568 00569 if( input_volume_header_only( filename, N_DIMENSIONS, 00570 File_order_dimension_names, 00571 &file_volume_3d, NULL ) != OK ) 00572 return( ERROR ); 00573 00574 get_volume_sizes( file_volume_3d, file_sizes ); 00575 00576 file_volume = create_volume( 2, File_order_dimension_names, 00577 NC_UNSPECIFIED, FALSE, 0.0, 0.0 ); 00578 00579 file = initialize_minc_input( filename, file_volume, NULL ); 00580 00581 if( file == NULL ) 00582 return( ERROR ); 00583 00584 n_slices = get_n_input_volumes( file ); 00585 00586 if( n_slices != file_sizes[0] ) 00587 { 00588 print_error( "load_label_volume(): error in sizes: %d %d\n", 00589 n_slices, file_sizes[0] ); 00590 } 00591 00592 /*--- check if the voxel1-to-voxel2 transform is linear */ 00593 00594 is_linear = get_transform_type( 00595 get_voxel_to_world_transform(label_volume) ) == LINEAR && 00596 get_transform_type( 00597 get_voxel_to_world_transform(file_volume_3d) ) == LINEAR; 00598 is_integer_step = FALSE; 00599 00600 if( is_linear ) 00601 { 00602 convert_3D_voxel_to_world( label_volume, 0.0, 0.0, 0.0, 00603 &xw, &yw, &zw ); 00604 convert_world_to_voxel( file_volume_3d, xw, yw, zw, start_voxel ); 00605 00606 convert_3D_voxel_to_world( label_volume, 0.0, 0.0, 1.0, 00607 &xw, &yw, &zw ); 00608 convert_world_to_voxel( file_volume_3d, xw, yw, zw, end_voxel ); 00609 00610 z_dx = end_voxel[0] - start_voxel[0]; 00611 z_dy = end_voxel[1] - start_voxel[1]; 00612 z_dz = end_voxel[2] - start_voxel[2]; 00613 00614 convert_3D_voxel_to_world( label_volume, 0.0, 1.0, 0.0, 00615 &xw, &yw, &zw ); 00616 convert_world_to_voxel( file_volume_3d, xw, yw, zw, end_voxel ); 00617 00618 y_dx = end_voxel[0] - start_voxel[0]; 00619 y_dy = end_voxel[1] - start_voxel[1]; 00620 y_dz = end_voxel[2] - start_voxel[2]; 00621 00622 is_integer_step = FALSE; 00623 if( IS_INT(z_dx) && IS_INT(z_dy) && IS_INT(z_dz) && 00624 IS_INT(y_dx) && IS_INT(y_dy) && IS_INT(y_dz) ) 00625 { 00626 is_integer_step = TRUE; 00627 int_z_dx = (int) z_dx; 00628 int_z_dy = (int) z_dy; 00629 int_z_dz = (int) z_dz; 00630 int_y_dx = (int) y_dx; 00631 int_y_dy = (int) y_dy; 00632 int_y_dz = (int) y_dz; 00633 } 00634 } 00635 00636 /*--- input label slices */ 00637 00638 initialize_progress_report( &progress, FALSE, n_slices, 00639 "Reading Labels" ); 00640 00641 for_less( slice, 0, n_slices ) 00642 { 00643 while( input_more_minc_file( file, &amount_done ) ) 00644 {} 00645 00646 get_input_volume_label_limits( label_volume, file_volume_3d, 00647 slice, limits ); 00648 00649 for_inclusive( label_voxel[X], limits[0][X], limits[1][X] ) 00650 { 00651 for_inclusive( label_voxel[Y], limits[0][Y], limits[1][Y] ) 00652 { 00653 if( is_linear ) 00654 { 00655 if( label_voxel[Y] == limits[0][Y] ) 00656 { 00657 convert_3D_voxel_to_world( label_volume, 00658 (Real) label_voxel[X], 00659 (Real) label_voxel[Y], 00660 (Real) limits[0][Z], 00661 &xw, &yw, &zw ); 00662 convert_world_to_voxel( file_volume_3d, xw, yw, zw, 00663 y_voxel ); 00664 y_voxel[X] += 0.5; 00665 y_voxel[Y] += 0.5; 00666 y_voxel[Z] += 0.5; 00667 00668 if( is_integer_step ) 00669 { 00670 int_y_voxel[X] = FLOOR( y_voxel[X] ); 00671 int_y_voxel[Y] = FLOOR( y_voxel[Y] ); 00672 int_y_voxel[Z] = FLOOR( y_voxel[Z] ); 00673 } 00674 } 00675 else 00676 { 00677 if( is_integer_step ) 00678 { 00679 int_y_voxel[X] += int_y_dx; 00680 int_y_voxel[Y] += int_y_dy; 00681 int_y_voxel[Z] += int_y_dz; 00682 } 00683 else 00684 { 00685 y_voxel[X] += y_dx; 00686 y_voxel[Y] += y_dy; 00687 y_voxel[Z] += y_dz; 00688 } 00689 } 00690 00691 if( is_integer_step ) 00692 { 00693 int_voxel[X] = int_y_voxel[X]; 00694 int_voxel[Y] = int_y_voxel[Y]; 00695 int_voxel[Z] = int_y_voxel[Z]; 00696 } 00697 else 00698 { 00699 voxel[X] = y_voxel[X]; 00700 voxel[Y] = y_voxel[Y]; 00701 voxel[Z] = y_voxel[Z]; 00702 } 00703 } 00704 00705 for_inclusive( label_voxel[Z], limits[0][Z], limits[1][Z] ) 00706 { 00707 if( !is_linear ) 00708 { 00709 convert_3D_voxel_to_world( label_volume, 00710 (Real) label_voxel[X], 00711 (Real) label_voxel[Y], 00712 (Real) label_voxel[Z], 00713 &xw, &yw, &zw ); 00714 convert_world_to_voxel( file_volume_3d, xw, yw, zw, 00715 voxel ); 00716 voxel[X] += 0.5; 00717 voxel[Y] += 0.5; 00718 voxel[Z] += 0.5; 00719 } 00720 else if( label_voxel[Z] != limits[0][Z] ) 00721 { 00722 if( is_integer_step ) 00723 { 00724 int_voxel[X] += int_z_dx; 00725 int_voxel[Y] += int_z_dy; 00726 int_voxel[Z] += int_z_dz; 00727 } 00728 else 00729 { 00730 voxel[X] += z_dx; 00731 voxel[Y] += z_dy; 00732 voxel[Z] += z_dz; 00733 } 00734 } 00735 00736 if( !is_integer_step ) 00737 { 00738 int_voxel[X] = FLOOR( voxel[X] ); 00739 int_voxel[Y] = FLOOR( voxel[Y] ); 00740 int_voxel[Z] = FLOOR( voxel[Z] ); 00741 } 00742 00743 if( int_voxel[X] == slice && 00744 int_voxel[Y] >= 0 && int_voxel[Y] < file_sizes[Y] && 00745 int_voxel[Z] >= 0 && int_voxel[Z] < file_sizes[Z] ) 00746 { 00747 file_value = get_volume_real_value( file_volume, 00748 int_voxel[Y], int_voxel[Z], 0, 0, 0 ); 00749 00750 if( file_value > 0.0 ) 00751 { 00752 int_file_value = ROUND( file_value ); 00753 set_volume_label_data( label_volume, label_voxel, 00754 int_file_value ); 00755 } 00756 } 00757 } 00758 } 00759 } 00760 00761 (void) advance_input_volume( file ); 00762 00763 update_progress_report( &progress, slice+1 ); 00764 } 00765 00766 terminate_progress_report( &progress ); 00767 00768 delete_volume( file_volume ); 00769 delete_volume( file_volume_3d ); 00770 00771 (void) close_minc_input( file ); 00772 00773 return( OK ); 00774 } 00775 00776 /* ----------------------------- MNI Header ----------------------------------- 00777 @NAME : save_label_volume 00778 @INPUT : filename 00779 original_filename 00780 label_volume 00781 @OUTPUT : 00782 @RETURNS : OK or ERROR 00783 @DESCRIPTION: Saves the label volume. 00784 @METHOD : 00785 @GLOBALS : 00786 @CALLS : 00787 @CREATED : 1993 David MacDonald 00788 @MODIFIED : Aug. 1, 1995 D. MacDonald - crops the volume on output 00789 ---------------------------------------------------------------------------- */ 00790 00791 public Status save_label_volume( 00792 STRING filename, 00793 STRING original_filename, 00794 Volume label_volume, 00795 Real crop_threshold ) 00796 { 00797 Status status; 00798 BOOLEAN cropping; 00799 Volume cropped_volume; 00800 int n_voxels, n_voxels_cropped; 00801 int c, limits[2][MAX_DIMENSIONS], sizes[MAX_DIMENSIONS]; 00802 00803 check_alloc_label_data( label_volume ); 00804 00805 if( crop_threshold > 0.0 ) 00806 { 00807 if( find_volume_crop_bounds( label_volume, -1.0, 0.5, limits ) ) 00808 { 00809 get_volume_sizes( label_volume, sizes ); 00810 n_voxels = 1; 00811 n_voxels_cropped = 1; 00812 for_less( c, 0, N_DIMENSIONS ) 00813 { 00814 n_voxels *= sizes[c]; 00815 n_voxels_cropped *= limits[1][c] - limits[0][c] + 1; 00816 } 00817 00818 cropping = ((Real) n_voxels_cropped / (Real) n_voxels < 00819 crop_threshold); 00820 } 00821 else 00822 { 00823 for_less( c, 0, N_DIMENSIONS ) 00824 { 00825 limits[0][c] = 0; 00826 limits[1][c] = 0; 00827 } 00828 cropping = TRUE; 00829 } 00830 } 00831 else 00832 cropping = FALSE; 00833 00834 if( cropping ) 00835 cropped_volume = create_cropped_volume( label_volume, limits ); 00836 else 00837 cropped_volume = label_volume; 00838 00839 if( original_filename != NULL ) 00840 { 00841 status = output_modified_volume( filename, 00842 NC_UNSPECIFIED, FALSE, 0.0, 0.0, 00843 cropped_volume, original_filename, 00844 "Label volume\n", NULL ); 00845 } 00846 else 00847 { 00848 status = output_volume( filename, NC_UNSPECIFIED, FALSE, 0.0, 0.0, 00849 cropped_volume, "Label volume\n", NULL ); 00850 } 00851 00852 if( cropping ) 00853 delete_volume( cropped_volume ); 00854 00855 return( status ); 00856 } 00857 00858 /* ----------------------------- MNI Header ----------------------------------- 00859 @NAME : input_tags_as_labels 00860 @INPUT : file 00861 volume 00862 @OUTPUT : label_volume 00863 @RETURNS : OK or ERROR 00864 @DESCRIPTION: Inputs a tag file into a label volume. 00865 @METHOD : 00866 @GLOBALS : 00867 @CALLS : 00868 @CREATED : 1993 David MacDonald 00869 @MODIFIED : 00870 ---------------------------------------------------------------------------- */ 00871 00872 public Status input_tags_as_labels( 00873 FILE *file, 00874 Volume volume, 00875 Volume label_volume ) 00876 { 00877 Status status; 00878 int c, label, ind[MAX_DIMENSIONS]; 00879 Real voxel[MAX_DIMENSIONS]; 00880 int n_volumes; 00881 Real tag1[N_DIMENSIONS]; 00882 int structure_id; 00883 Real min_label, max_label; 00884 00885 check_alloc_label_data( label_volume ); 00886 00887 get_volume_real_range( label_volume, &min_label, &max_label ); 00888 00889 status = initialize_tag_file_input( file, &n_volumes ); 00890 00891 while( status == OK && 00892 input_one_tag( file, n_volumes, 00893 tag1, NULL, NULL, &structure_id, NULL, NULL, 00894 &status ) ) 00895 { 00896 convert_world_to_voxel( volume, tag1[X], tag1[Y], tag1[Z], voxel ); 00897 00898 for_less( c, 0, get_volume_n_dimensions(volume) ) 00899 { 00900 ind[c] = ROUND( voxel[c] ); 00901 } 00902 00903 label = structure_id; 00904 if( (Real) label >= min_label && (Real) label <= max_label && 00905 int_voxel_is_within_volume( volume, ind ) ) 00906 { 00907 set_volume_label_data( label_volume, ind, label); 00908 } 00909 } 00910 00911 return( status ); 00912 } 00913 00914 /* ----------------------------- MNI Header ----------------------------------- 00915 @NAME : create_label_volume_from_file 00916 @INPUT : filename 00917 volume 00918 @OUTPUT : label_volume 00919 @RETURNS : OK or ERROR 00920 @DESCRIPTION: Creates a label volume for the given volume from a tag file or 00921 a minc file. 00922 @METHOD : 00923 @GLOBALS : 00924 @CALLS : 00925 @CREATED : Dec. 8, 1995 David MacDonald 00926 @MODIFIED : 00927 ---------------------------------------------------------------------------- */ 00928 00929 public Status create_label_volume_from_file( 00930 STRING filename, 00931 Volume volume, 00932 Volume *label_volume ) 00933 { 00934 Status status; 00935 STRING *dim_names; 00936 Volume file_volume; 00937 FILE *file; 00938 BOOLEAN same_grid; 00939 00940 status = OK; 00941 00942 if( filename_extension_matches( filename, "mnc" ) ) 00943 { 00944 dim_names = get_volume_dimension_names( volume ); 00945 status = input_volume_header_only( filename, 00946 get_volume_n_dimensions(volume), 00947 dim_names, &file_volume, NULL ); 00948 00949 if( status != OK ) 00950 { 00951 delete_dimension_names( volume, dim_names ); 00952 return( status ); 00953 } 00954 00955 same_grid = volumes_are_same_grid( volume, file_volume ); 00956 delete_volume( file_volume ); 00957 00958 if( same_grid ) 00959 { 00960 status = input_volume( filename, get_volume_n_dimensions(volume), 00961 dim_names, NC_UNSPECIFIED, FALSE, 0.0, 0.0, 00962 TRUE, label_volume, NULL ); 00963 } 00964 else 00965 { 00966 *label_volume = create_label_volume( volume, NC_UNSPECIFIED ); 00967 status = load_label_volume( filename, *label_volume ); 00968 } 00969 00970 delete_dimension_names( volume, dim_names ); 00971 } 00972 else 00973 { 00974 *label_volume = create_label_volume( volume, NC_UNSPECIFIED ); 00975 00976 if( open_file( filename, READ_FILE, ASCII_FORMAT, &file )!=OK) 00977 return( ERROR ); 00978 00979 if( input_tags_as_labels( file, volume, *label_volume ) != OK ) 00980 return( ERROR ); 00981 00982 (void) close_file( file ); 00983 } 00984 00985 return( status ); 00986 } 00987 00988 /* ----------------------------- MNI Header ----------------------------------- 00989 @NAME : output_labels_as_tags 00990 @INPUT : file 00991 volume 00992 label_volume 00993 desired_label 00994 size 00995 patient_id 00996 @OUTPUT : 00997 @RETURNS : OK or ERROR 00998 @DESCRIPTION: Outputs a set of labels as tags. 00999 @METHOD : 01000 @GLOBALS : 01001 @CALLS : 01002 @CREATED : 1993 David MacDonald 01003 @MODIFIED : Oct. 19, 1995 D. MacDonald - now writes tags 1 at a time to 01004 be more memory efficient. 01005 ---------------------------------------------------------------------------- */ 01006 01007 public Status output_labels_as_tags( 01008 FILE *file, 01009 Volume volume, 01010 Volume label_volume, 01011 int desired_label, 01012 Real size, 01013 int patient_id ) 01014 { 01015 int ind[N_DIMENSIONS]; 01016 int label, sizes[MAX_DIMENSIONS]; 01017 Real real_ind[N_DIMENSIONS]; 01018 Real tags[N_DIMENSIONS]; 01019 int n_tags; 01020 01021 if( get_volume_n_dimensions(volume) != 3 ) 01022 { 01023 print_error( "output_labels_as_tags: volume must be 3D\n" ); 01024 return( ERROR ); 01025 } 01026 01027 check_alloc_label_data( label_volume ); 01028 get_volume_sizes( label_volume, sizes ); 01029 01030 n_tags = 0; 01031 01032 for_less( ind[X], 0, sizes[X] ) 01033 { 01034 real_ind[X] = (Real) ind[X]; 01035 for_less( ind[Y], 0, sizes[Y] ) 01036 { 01037 real_ind[Y] = (Real) ind[Y]; 01038 for_less( ind[Z], 0, sizes[Z] ) 01039 { 01040 real_ind[Z] = (Real) ind[Z]; 01041 label = get_volume_label_data( label_volume, ind ); 01042 01043 if( label == desired_label || (desired_label < 0 && label > 0) ) 01044 { 01045 convert_voxel_to_world( volume, real_ind, 01046 &tags[X], &tags[Y], &tags[Z] ); 01047 01048 if( n_tags == 0 && 01049 initialize_tag_file_output( file, NULL, 1 ) != OK ) 01050 return( ERROR ); 01051 01052 if( output_one_tag( file, 1, tags, NULL, 01053 &size, &label, &patient_id, NULL ) != OK ) 01054 return( ERROR ); 01055 01056 ++n_tags; 01057 } 01058 } 01059 } 01060 } 01061 01062 if( n_tags > 0 ) 01063 terminate_tag_file_output( file ); 01064 01065 return( OK ); 01066 } 01067 01068 /* ----------------------------- MNI Header ----------------------------------- 01069 @NAME : input_landmarks_as_labels 01070 @INPUT : file 01071 volume 01072 @OUTPUT : label_volume 01073 @RETURNS : OK or ERROR 01074 @DESCRIPTION: Loads a set of landmarks into the label_volume. 01075 @METHOD : 01076 @GLOBALS : 01077 @CALLS : 01078 @CREATED : 1993 David MacDonald 01079 @MODIFIED : Oct. 19, 1995 D. MacDonald - now reads tags 1 at a time to 01080 be more memory efficient. 01081 ---------------------------------------------------------------------------- */ 01082 01083 public Status input_landmarks_as_labels( 01084 FILE *file, 01085 Volume volume, 01086 Volume label_volume ) 01087 { 01088 int c, label, ind[MAX_DIMENSIONS]; 01089 Real voxel[MAX_DIMENSIONS]; 01090 marker_struct marker; 01091 Real min_label, max_label; 01092 01093 check_alloc_label_data( label_volume ); 01094 01095 get_volume_real_range( label_volume, &min_label, &max_label ); 01096 01097 while( io_tag_point( file, READ_FILE, volume, 1.0, &marker ) == OK ) 01098 { 01099 convert_world_to_voxel( volume, 01100 (Real) Point_x(marker.position), 01101 (Real) Point_y(marker.position), 01102 (Real) Point_z(marker.position), voxel ); 01103 01104 for_less( c, 0, get_volume_n_dimensions(volume) ) 01105 ind[c] = ROUND( voxel[c] ); 01106 01107 label = marker.structure_id; 01108 if( (Real) label >= min_label && (Real) label <= max_label && 01109 int_voxel_is_within_volume( volume, ind ) ) 01110 { 01111 set_volume_label_data( label_volume, ind, label ); 01112 } 01113 } 01114 01115 return( OK ); 01116 }

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7