00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
#include <volume_io/internal_volume_io.h>
00016
#include <bicpl/numerical.h>
00017
00018
#ifndef lint
00019
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Numerical/histogram.c,v 1.11 2000/02/06 15:30:39 stever Exp $";
00020
#endif
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 public void initialize_histogram(
00038
histogram_struct *histogram,
00039 Real delta,
00040 Real offset )
00041 {
00042 histogram->
delta = delta;
00043 histogram->
offset = offset;
00044
00045 histogram->
min_index = 0;
00046 histogram->
max_index = -1;
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 public void delete_histogram(
00063
histogram_struct *histogram )
00064 {
00065
if( histogram->
max_index >= histogram->
min_index )
00066 {
00067 FREE( histogram->
counts );
00068 }
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 private int get_histogram_index(
00087
histogram_struct *histogram,
00088 Real value )
00089 {
00090
int ind;
00091
00092 ind = FLOOR( (value - histogram->
offset) / histogram->
delta );
00093
00094
return( ind );
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 private Real
convert_real_index_to_value(
00112
histogram_struct *histogram,
00113 Real ind )
00114 {
00115
return( ind * histogram->
delta + histogram->
offset );
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 private Real
convert_index_to_value(
00134
histogram_struct *histogram,
00135
int ind )
00136 {
00137
return(
convert_real_index_to_value( histogram, (Real) ind ) );
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 public void add_to_histogram(
00157
histogram_struct *histogram,
00158 Real value )
00159 {
00160
int ind, i, prev_size, new_size;
00161
00162 ind =
get_histogram_index( histogram, value );
00163
00164
if( histogram->
min_index > histogram->
max_index )
00165 {
00166 ALLOC( histogram->
counts, 1 );
00167 histogram->
counts[0] = 0;
00168 histogram->
min_index = ind;
00169 histogram->
max_index = ind;
00170 }
00171
else if( ind < histogram->
min_index )
00172 {
00173 prev_size = histogram->
max_index - histogram->
min_index + 1;
00174 new_size = histogram->
max_index - ind + 1;
00175 SET_ARRAY_SIZE( histogram->
counts, prev_size, new_size, 1 );
00176
00177 for_down( i, histogram->
max_index, histogram->
min_index )
00178 {
00179 histogram->
counts[i-ind] =
00180 histogram->
counts[i-histogram->
min_index];
00181 }
00182
00183 for_less( i, ind, histogram->
min_index )
00184 histogram->
counts[i-ind] = 0;
00185
00186 histogram->
min_index = ind;
00187 }
00188
else if( ind > histogram->
max_index )
00189 {
00190 prev_size = histogram->
max_index - histogram->
min_index + 1;
00191 new_size = ind - histogram->
min_index + 1;
00192 SET_ARRAY_SIZE( histogram->
counts, prev_size, new_size, 1 );
00193
00194 for_inclusive( i, histogram->
max_index + 1, ind )
00195 histogram->
counts[i-histogram->
min_index] = 0;
00196
00197 histogram->
max_index = ind;
00198 }
00199
00200 ++histogram->
counts[ind-histogram->
min_index];
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 private void get_histogram_range(
00219
histogram_struct *histogram,
00220 Real *min_value,
00221 Real *max_value )
00222 {
00223 *min_value =
convert_index_to_value( histogram, histogram->
min_index );
00224 *max_value =
convert_index_to_value( histogram, histogram->
max_index + 1 );
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 private int get_histogram_max_count(
00241
histogram_struct *histogram )
00242 {
00243
int ind, max_count;
00244
00245 max_count = 0;
00246 for_inclusive( ind, histogram->
min_index, histogram->
max_index )
00247 {
00248
if( ind == 0 ||
00249 histogram->
counts[ind-histogram->
min_index] > max_count )
00250 max_count = histogram->
counts[ind-histogram->
min_index];
00251 }
00252
00253
return( max_count );
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 private void box_filter_histogram(
00274
int n,
00275 Real counts[],
00276 Real new_counts[],
00277
int half_width )
00278 {
00279
int i, window_width, start_index, end_index;
00280 Real current_value;
00281
00282 start_index = - half_width;
00283 end_index = half_width;
00284
00285 current_value = 0.0;
00286 for_inclusive( i, 0, MIN( end_index, n-1 ) )
00287 current_value += counts[i];
00288
00289 for_less( i, 0, n )
00290 {
00291 window_width = MIN( end_index, n-1 ) - MAX( start_index, 0 ) + 1;
00292 new_counts[i] = (Real) current_value / (Real) window_width;
00293
if( start_index >= 0 )
00294 current_value -= counts[start_index];
00295 ++start_index;
00296 ++end_index;
00297
if( end_index < n )
00298 current_value += counts[end_index];
00299 }
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 public int get_histogram_counts(
00321
histogram_struct *histogram,
00322 Real *counts[],
00323 Real filter_width,
00324 Real *scale_factor,
00325 Real *trans_factor )
00326 {
00327
int i, n, width;
00328 Real *tmp_counts;
00329
00330 n = histogram->
max_index - histogram->
min_index + 1;
00331
00332
if( n <= 0 )
00333
return( 0 );
00334
00335 ALLOC( tmp_counts, n );
00336 ALLOC( *counts, n );
00337
00338 for_less( i, 0, n )
00339 tmp_counts[i] = (Real) histogram->
counts[i];
00340
00341 width = ROUND( filter_width / histogram->
delta / 2.0 );
00342
00343
box_filter_histogram( n, tmp_counts, *counts, width );
00344
00345 FREE( tmp_counts );
00346
00347 *scale_factor = histogram->
delta;
00348 *trans_factor =
convert_real_index_to_value( histogram,
00349 (Real) histogram->
min_index + 0.5 );
00350
00351
return( n );
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 private void resample_histogram(
00373
histogram_struct *histogram,
00374
int x_size,
00375
int y_size,
00376 Real *x_scale,
00377 Real *x_trans,
00378 Real height[] )
00379 {
00380
int ind, x, max_count, left_ind, right_ind;
00381 Real weight, sum_count, min_value, max_value;
00382 Real left_side, right_side, left, right;
00383
00384
get_histogram_range( histogram, &min_value, &max_value );
00385
00386
if( max_value <= min_value )
00387 {
00388 for_less( x, 0, x_size )
00389 height[x] = 0.0;
00390 *x_scale = 1.0;
00391 *x_trans = 0.0;
00392
return;
00393 }
00394
00395 max_count =
get_histogram_max_count( histogram );
00396
00397 *x_scale = 1.0 / (Real) x_size * (max_value - min_value);
00398 *x_trans = min_value + 0.5 * (*x_scale);
00399
00400 for_less( x, 0, x_size )
00401 {
00402 left = min_value + (Real) x / (Real) x_size * (max_value - min_value);
00403 right = min_value + (Real) (x+1) / (Real) x_size *
00404 (max_value - min_value);
00405
00406 left_ind =
get_histogram_index( histogram, left );
00407 right_ind =
get_histogram_index( histogram, right );
00408
00409 sum_count = 0.0;
00410
00411 for_inclusive( ind, left_ind, right_ind )
00412 {
00413 left_side =
convert_index_to_value( histogram, ind );
00414 right_side =
convert_index_to_value( histogram, ind+1 );
00415
00416 weight = MIN( right_side, right ) - MAX( left_side, left );
00417
00418 sum_count += weight *
00419 (Real) histogram->
counts[ind-histogram->
min_index];
00420 }
00421
00422 height[x] = sum_count / (right - left) * (Real) y_size /
00423 (Real) max_count;
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 public void display_histogram(
00443
histogram_struct *histogram,
00444
int x_size,
00445
int y_size )
00446 {
00447
int x,
y, max_count;
00448 Real min_value, max_value, *n_chars, x_scale, x_trans;
00449
00450 ALLOC( n_chars, x_size );
00451
00452
resample_histogram( histogram, x_size, y_size, &x_scale, &x_trans,
00453 n_chars );
00454
00455
for(
y = y_size-1;
y >= 0; --
y )
00456 {
00457 for_less( x, 0, x_size )
00458 {
00459
if(
y < ROUND(n_chars[x]) )
00460 print(
"#" );
00461
else
00462 print(
" " );
00463 }
00464
00465 print(
"\n" );
00466 }
00467
00468
get_histogram_range( histogram, &min_value, &max_value );
00469 max_count =
get_histogram_max_count( histogram );
00470
00471 print(
"%g to %g with max count = %d\n", min_value, max_value, max_count );
00472
00473 FREE( n_chars );
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 public void create_histogram_line(
00493
histogram_struct *histogram,
00494
int x_size,
00495
int y_size,
00496 Real filter_width,
00497
lines_struct *lines )
00498 {
00499
int x, width;
00500 Real *height, *smooth_height, x_scale, x_trans;
00501 Point p;
00502
00503 ALLOC( height, x_size );
00504
00505
resample_histogram( histogram, x_size, y_size, &x_scale, &x_trans, height );
00506
00507 width = ROUND( filter_width / x_scale / 2.0 );
00508
00509 ALLOC( smooth_height, x_size );
00510
00511
box_filter_histogram( x_size, height, smooth_height, width );
00512
00513
initialize_lines( lines,
WHITE );
00514
00515 for_less( x, 0, x_size )
00516 {
00517 fill_Point( p, (Real) x * x_scale + x_trans, smooth_height[x], 0.0 );
00518
add_point_to_line( lines, &p );
00519 }
00520
00521 FREE( height );
00522 FREE( smooth_height );
00523 }