1 //---
2 //
3 // License: MIT
4 //
5 // Author: Ken Melero (kmelero@imagelinks.com)
6 // Orginally developed by:
7 // Copyright (c) 1997 TargetJr Consortium
8 // GE Corporate Research and Development (GE CRD)
9 // 1 Research Circle
10 // Niskayuna, NY 12309
11 // Adapted from: IUE v4.1.2
12 // Description:
13 // A ossimHistogram contains an array of "buckets", which represent finite
14 // segments of some value axis, along with a corresponding array of
15 // frequency m_counts for each of these buckets.
16 //
17 //---
18 // $Id$
19
20 #include <ossim/base/ossimCommon.h>
21 #include <ossim/base/ossimHistogram.h>
22 #include <ossim/base/ossimNotifyContext.h>
23 #include <ossim/base/ossimScalarTypeLut.h>
24 #include <ossim/base/ossimThinPlateSpline.h>
25 #include <ossim/base/ossimDpt.h>
26 #include <cmath>
27 #include <cstdio>
28 #include <fstream>
29 #include <iostream>
30 #include <iomanip>
31 #include <sstream>
32 using namespace std;
33
34 // nonstandard versions that use operator>, so they behave differently
35 // than std:::min/max and ossim::min/max. kept here for now for that
36 // reason.
37 #ifndef MAX
38 # define MAX(x,y) ((x)>(y)?(x):(y))
39 # define MIN(x,y) ((x)>(y)?(y):(x))
40 #endif
41
42
43 static const int MEAN_FLAG = 1, SD_FLAG = 2;
44 RTTI_DEF1(ossimHistogram, "ossimHistogram", ossimObject);
ossimHistogram()45 ossimHistogram::ossimHistogram()
46 :
47 m_statsConsistent(MEAN_FLAG | SD_FLAG),
48 m_vals(new double [1]),
49 m_counts(new ossim_int64 [1]),
50 m_num(0),
51 m_delta(0.0),
52 m_vmin(0),
53 m_vmax(0),
54 m_mean(0.0),
55 m_standardDev(0.0),
56 m_nullValue(ossim::nan()),
57 m_nullCount(0),
58 m_scalarType(OSSIM_SCALAR_UNKNOWN)
59 {
60 m_vals[0] = 0.0;
61 m_counts[0] = 0.0;
62 }
63
ossimHistogram(int xres,double val1,double val2,double nullValue,ossimScalarType scalar)64 ossimHistogram::ossimHistogram(int xres, double val1, double val2, double nullValue, ossimScalarType scalar)
65 :
66 m_statsConsistent(MEAN_FLAG | SD_FLAG),
67 m_vals(new double [xres]),
68 m_counts(new ossim_int64 [xres]),
69 m_num(xres),
70 m_delta(0.0),
71 m_vmin(0),
72 m_vmax(0),
73 m_mean(0.0),
74 m_standardDev(0.0),
75 m_nullValue(nullValue),
76 m_nullCount(0),
77 m_scalarType(scalar)
78 {
79 m_vmax = MAX(val1, val2);
80 m_vmin = MIN(val1, val2);
81
82 //---
83 // Set the delta which is used to index the bins.
84 // Note: that using "(m_vmax - m_vmin) / xres" was dropping the
85 // last bin on integer data.
86 //---
87 if ( (m_vmax - m_vmin + 1) == xres )
88 {
89 m_delta = 1.0;
90 }
91 else
92 {
93 if ( ossim::isInteger(scalar) )
94 {
95 m_delta = (m_vmax - m_vmin + 1) / xres;
96 }
97 else
98 {
99 m_delta = (m_vmax - m_vmin) / xres;
100 }
101 }
102
103 m_mean = (double)((m_vmax + m_vmin)/2.0);
104 m_standardDev = (double)((m_vmax - m_vmin)/(2.0*sqrt(3.0)));
105 int i = 0;
106
107 if (m_vals == NULL || m_counts == NULL)
108 {
109 fprintf(stderr, "Histogram : Ran out of memory for arrays.\n");
110 m_vals = NULL;
111 m_counts = NULL;
112 m_num = 0;
113 m_vmin = 0;
114 m_vmax = 0;
115 m_delta = 0.0;
116 }
117 else
118 {
119 if ( ossim::isInteger( m_scalarType ) )
120 {
121 for(i = 0; i < xres; i++)
122 {
123 m_vals[i] = m_vmin + m_delta * (double)i;
124 m_counts[i] = 0;
125 }
126 }
127 else
128 {
129 for(i = 0; i < xres; i++)
130 {
131 m_vals[i] = m_vmin + m_delta * (double)(i + 0.5);
132 m_counts[i] = 0;
133 }
134 }
135 }
136 }
137
138 #if 0
139 ossimHistogram::ossimHistogram(double* uvals, double* ucounts, int xres)
140 :
141 m_statsConsistent(MEAN_FLAG | SD_FLAG),
142 m_vals(uvals),
143 m_counts(ucounts),
144 m_num(xres),
145 m_delta(0.0),
146 m_vmin(0),
147 m_vmax(0),
148 m_mean(0.0),
149 m_standardDev(0.0),
150 m_nullValue(ossim::nan()),
151 m_nullCount(0),
152 m_scalarType(OSSIM_SCALAR_UNKNOWN)
153 {
154 if ( ( xres >= 2 ) && uvals && ucounts )
155 {
156 m_delta = m_vals[1] - m_vals[0]; // Changed this from delta = 1.0
157 // m_vmax = GetMaxVal();
158 // m_vmin = GetMinVal(); JAF version
159 m_vmin = uvals[0] - .5f*m_delta;
160 m_vmax = uvals[m_num-1] + .5f*m_delta;
161 m_mean = GetMean();
162 m_standardDev = GetStandardDev();
163 }
164 }
165 #endif
166
ossimHistogram(const double * data,ossim_uint32 size,ossim_uint32 xres)167 ossimHistogram::ossimHistogram(const double* data, ossim_uint32 size, ossim_uint32 xres)
168 :
169 m_statsConsistent(0),
170 m_vals(0),
171 m_counts(0),
172 m_num((int)xres),
173 m_delta(0.0),
174 m_vmin(0),
175 m_vmax(0),
176 m_mean(0.0),
177 m_standardDev(0.0),
178 m_nullValue(ossim::nan()),
179 m_nullCount(0),
180 m_scalarType(OSSIM_SCALAR_UNKNOWN)
181 {
182 if ((size == 0) || (xres == 0))
183 return;
184
185 // scan the dataset for min/max:
186 m_vmin=(double)(data[0]);
187 m_vmax=(double)(data[0]);
188 for (ossim_uint32 i=1; i<size; ++i)
189 {
190 if ((double)(data[i]) < m_vmin)
191 m_vmin = (double)(data[i]);
192 else if ((double)(data[i]) > m_vmax)
193 m_vmax = (double)(data[i]);
194 }
195
196 // Allocate histogram:
197
198 //---
199 // Set the delta which is used to index the bins.
200 // Note: that using "(m_vmax - m_vmin) / xres" was dropping the
201 // last bin on integer data.
202 //---
203 if ( (m_vmax - m_vmin + 1) == xres )
204 {
205 m_delta = 1.0;
206 }
207 else
208 {
209 m_delta = (m_vmax - m_vmin) / xres;
210 }
211
212 m_vals = new double [m_num];
213 m_counts = new ossim_int64 [m_num];
214 for (ossim_int32 i=0; i<m_num; ++i)
215 {
216 m_vals[i] = m_vmin + m_delta * (i + 0.5);
217 m_counts[i] = 0;
218 }
219
220 // compute histogram:
221 for (ossim_uint32 i=0; i<size; i++)
222 UpCount((double)(data[i]));
223
224 GetMean();
225 GetStandardDev();
226 }
227
228 //-----------------------------------------------------------
229 // -- Copy constructor
ossimHistogram(const ossimHistogram & his)230 ossimHistogram::ossimHistogram(const ossimHistogram& his)
231 :
232 m_statsConsistent(0),
233 m_vals(0),
234 m_counts(0),
235 m_num(0),
236 m_delta(0.0),
237 m_vmin(0),
238 m_vmax(0),
239 m_mean(0.0),
240 m_standardDev(0.0),
241 m_nullValue(his.m_nullValue),
242 m_nullCount(his.m_nullCount),
243 m_scalarType(his.m_scalarType)
244 {
245 int i = 0;
246 m_num = his.GetRes();
247
248 m_vals = new double[m_num];
249 const double* his_vals = his.GetVals();
250
251 m_counts = new ossim_int64[m_num];
252 const ossim_int64* his_counts = his.GetCounts();
253
254 if (m_vals == NULL || m_counts == NULL)
255 {
256 fprintf(stderr, "Histogram : Ran out of memory for arrays.\n");
257 m_vals = NULL;
258 m_counts = NULL;
259 m_num = 0;
260 m_vmin = 0;
261 m_vmax = 0;
262 m_delta = 0.0;
263 m_statsConsistent = 0;
264 return;
265 }
266
267 m_mean = his.GetMean();
268 m_standardDev = his.GetStandardDev();
269
270 for(i=0; i<m_num; i++)
271 {
272 m_vals[i] = his_vals[i];
273 m_counts[i] = his_counts[i];
274 }
275 m_vmax = his.GetMaxVal();
276 m_vmin = his.GetMinVal();
277 m_delta = his.GetBucketSize();
278
279 m_statsConsistent = 0;
280 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
281 }
282
283
284 //---------------------------------------
285 // -- Resample a histogram
ossimHistogram(const ossimHistogram * his,double width)286 ossimHistogram::ossimHistogram(const ossimHistogram* his, double width)
287 :
288 m_statsConsistent(0),
289 m_vals(0),
290 m_counts(0),
291 m_num(0),
292 m_delta(0.0),
293 m_vmin(0),
294 m_vmax(0),
295 m_mean(0.0),
296 m_standardDev(0.0),
297 m_nullValue(ossim::nan()),
298 m_nullCount(0),
299 m_scalarType(OSSIM_SCALAR_UNKNOWN)
300 {
301 if ( his )
302 {
303 m_statsConsistent =0;
304
305 // Attributes of original histogram
306 double del = his->GetBucketSize();
307 int max_index = his->GetRes() - 1;
308 double minvalue = his->GetVals()[0] - del*.5f;
309 double maxvalue = his->GetVals()[max_index] + del*.5f;
310
311 // Intialize a new histogram
312 m_nullValue = his->getNullValue();
313 m_nullCount = his->getNullCount();
314 m_scalarType = his->getScalarType();
315
316 if(width == del) m_num = his->GetRes();
317 else if(!(width == 0.0))
318 {
319 m_num = (int)ceil((maxvalue - minvalue)/width);
320 // if ( m_nullCount )
321 // {
322 // m_nullCount /= width; // ??? drb
323 // }
324 }
325 else
326 m_num = 1; // This shouldn't happen anyway.
327
328 m_vals = new double [m_num];
329 m_counts = new ossim_int64 [m_num];
330 m_delta = width;
331 double mean_val = (maxvalue + minvalue)/2.0f;
332 double half_range = (m_num * m_delta)/2.0f;
333 m_vmax = mean_val + half_range;
334 m_vmin = mean_val - half_range;
335 int i = 0;
336
337 if (m_vals == NULL || m_counts == NULL)
338 {
339 fprintf(stderr,
340 "Histogram : Ran out of memory for arrays.\n");
341 m_vals = NULL;
342 m_counts = NULL;
343 m_num = 0;
344 m_vmin = 0;
345 m_vmax = 0;
346 m_delta = 0.0;
347 m_mean = 0.0;
348 m_standardDev = 0.0;
349 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
350 return;
351
352 }
353
354 else
355 {
356 for(i = 0; i < m_num; i++)
357 {
358 m_vals[i] = m_vmin + m_delta * (i + 0.5f);
359 m_counts[i] = 0;
360 }
361 }
362
363
364 // Cases:
365
366
367 if(width == del) // Then just copy his
368 {
369 const ossim_int64* his_counts = his->GetCounts();
370 for(i=0; i<m_num; i++)
371 m_counts[i] = his_counts[i];
372 m_mean = GetMean();
373 m_standardDev = GetStandardDev();
374 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
375 return;
376 }
377
378
379 if(del > width) // Then interpolate his m_counts.
380 {
381
382 // Boundary conditions:
383 // Start
384 double his_start = minvalue + .5f*del;
385 double start = m_vmin + .5f*m_delta;
386 double c0 = his->GetCount(his_start);
387 double c1 = his->GetCount(his_start + del);
388 double s0 = (c1 - c0)/del;
389
390 for(double x = start; x <= (his_start + del + m_delta);)
391 {
392 double interp = s0 * (x - his_start) + c0;
393 if(interp < 0) interp = 0; //Can be negative
394 SetCount(x,interp);
395 x += width;
396 }
397 // End
398 double his_end = maxvalue - .5f*del;
399 double end = m_vmax - .5f*m_delta;
400 double cn = his->GetCount(his_end);
401 double cn_1 = his->GetCount(his_end - del);
402 double sn = (cn_1 - cn)/del;
403
404 for(double y = end; y >= (his_end - del + m_delta);)
405 {
406 double interp = sn * (his_end - y) + cn;
407 if(interp < 0) interp = 0; //Can be negative
408 SetCount(y, interp);
409 y -= m_delta;
410 }
411 // Interior Loop
412
413 for(double z = his_start + del; z <= (his_end - del);)
414 {
415 double ci = his->GetCount(z);
416 double ci_1 = his->GetCount(z-del);
417 double cip1 = his->GetCount(z+del);
418 double deriv = (cip1 - ci_1)/(2.0f*del);
419 double second_drv =
420 ((cip1 + ci_1)/2.0f - ci)/(del*del);
421 int fine_x_index = GetIndex(z);
422 if (fine_x_index < 0)
423 {
424 if (z<m_vmin) fine_x_index = 0;
425 else fine_x_index = m_num-1;
426 }
427 double fine_x = m_vals[fine_x_index];
428 for(double xfine = fine_x; xfine < z + del;)
429 {
430 double interp = ci + deriv*(xfine -z) +
431 second_drv*(xfine - z)*(xfine - z);
432
433 if(interp < 0) interp = 0; //Can be negative
434 SetCount(xfine, interp);
435 xfine += width;
436 }
437 z += del;
438 }
439 }
440
441
442 if(del < width) //Just accumulate samples from his into larger bins
443 {
444 if( del != 0.0){
445 double his_start = minvalue + .5f*del;
446 double his_end = maxvalue - .5f*del;
447 for(double x = his_start; x <= his_end;)
448 {
449 SetCount(x, (GetCount(x) + his->GetCount(x)));
450 x += del;
451 }
452 }
453 }
454 m_mean = GetMean();
455 m_standardDev = GetStandardDev();
456 m_statsConsistent =0;
457 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
458 }
459 }
460
461 #if 0
462 void ossimHistogram::create(int xres, double val1, double val2)
463 {
464 // clear all the data
465 deleteAll();
466
467 // now set it up and initialize;
468 xres = xres >0? xres:1;
469
470 m_vals = new double [xres];
471 m_counts = new ossim_int64 [xres];
472 m_num = xres;
473 m_vmax = MAX(val1, val2);
474 m_vmin = MIN(val1, val2);
475
476 if ( (m_vmax - m_vmin + 1) == xres )
477 {
478 m_delta = 1.0;
479 }
480 else
481 {
482 m_delta = (m_vmax - m_vmin) / xres;
483 }
484
485 m_mean = (double)((m_vmax + m_vmin)/2.0);
486 m_standardDev = (double)((m_vmax - m_vmin)/(2.0*sqrt(3.0)));
487 m_statsConsistent = 0;
488 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
489 int i = 0;
490 if (m_vals == NULL || m_counts == NULL)
491 {
492 ossimNotify(ossimNotifyLevel_FATAL) << "Histogram : Ran out of memory for arrays.\n";
493 m_vals = NULL;
494 m_counts = NULL;
495 m_num = 0;
496 m_vmin = 0;
497 m_vmax = 0;
498 m_delta = 0.0;
499 }
500 else
501 {
502 for(i = 0; i < xres; i++)
503 {
504 m_vals[i] = m_vmin + m_delta * (double)(i + 0.5);
505 m_counts[i] = 0;
506 }
507 }
508 }
509 #endif
510
create(int bins,double minValue,double maxValue,ossim_float64 nullValue,ossimScalarType scalar)511 void ossimHistogram::create(
512 int bins, double minValue, double maxValue, ossim_float64 nullValue, ossimScalarType scalar)
513 {
514 // create( bins, minValue, maxValue);
515
516 // clear all the data
517 deleteAll();
518
519 // Must set null value after create call.
520 m_nullValue = nullValue;
521 m_scalarType = scalar;
522
523 // now set it up and initialize;
524 bins = bins >0? bins:1;
525
526 m_vals = new double [bins];
527 m_counts = new ossim_int64 [bins];
528 m_num = bins;
529 m_vmax = MAX(minValue, maxValue);
530 m_vmin = MIN(minValue, maxValue);
531
532 if ( (m_vmax - m_vmin + 1) == bins )
533 {
534 m_delta = 1.0;
535 }
536 else
537 {
538 m_delta = (m_vmax - m_vmin) / bins;
539 }
540
541 m_mean = (double)((m_vmax + m_vmin)/2.0);
542 m_standardDev = (double)((m_vmax - m_vmin)/(2.0*sqrt(3.0)));
543 m_statsConsistent = 0;
544 m_statsConsistent |= (MEAN_FLAG | SD_FLAG);
545 // int i = 0;
546 if (m_vals == NULL || m_counts == NULL)
547 {
548 ossimNotify(ossimNotifyLevel_FATAL) << "Histogram : Ran out of memory for arrays.\n";
549 m_vals = NULL;
550 m_counts = NULL;
551 m_num = 0;
552 m_vmin = 0;
553 m_vmax = 0;
554 m_delta = 0.0;
555 }
556 else
557 {
558 if (ossim::isInteger( m_scalarType ) )
559 {
560 for(int i = 0; i < bins; ++i)
561 {
562 m_vals[i] = m_vmin + m_delta * i;
563 m_counts[i] = 0;
564 }
565 }
566 else
567 {
568 for(int i = 0; i < bins; ++i)
569 {
570 m_vals[i] = m_vmin + m_delta * (double)(i + 0.5);
571 m_counts[i] = 0;
572 }
573 }
574 }
575 }
576
fillEmptyBins(bool interiorOnly,int type) const577 ossimRefPtr<ossimHistogram> ossimHistogram::fillEmptyBins(bool interiorOnly, int type) const
578 {
579 if(m_num < 1) return 0;
580 ossimRefPtr<ossimHistogram> result = new ossimHistogram(*this);
581 switch(type)
582 {
583 case HISTOGRAM_FILL_THIN_PLATE:
584 case HISTOGRAM_FILL_DEFAULT:
585 {
586 ossimThinPlateSpline spline(1);
587 double pvars[1];
588 ossim_int64* new_counts = result->GetCounts();
589 ossim_int32 idxLeft = 0;
590 ossim_int32 idxRight = m_num-1;
591 while((idxLeft < m_num) && (new_counts[idxLeft] < 1))++idxLeft;
592 while((idxRight > -1) && (new_counts[idxRight] < 1))--idxRight;
593 if(idxLeft < idxRight)
594 {
595 ossim_int32 idx = idxLeft;
596 while(idx <= idxRight)
597 {
598 if(new_counts[idx]>0)
599 {
600 pvars[0] = new_counts[idx];
601 spline.addPoint(idx, 0, pvars);
602 }
603 ++idx;
604 }
605 if(spline.solve())
606 {
607 idx = idxLeft;
608 while(idx <= idxRight)
609 {
610 if(spline.getPoint(idx, 0, pvars))
611 {
612 new_counts[idx] = pvars[0];
613 }
614 ++idx;
615 }
616 m_statsConsistent = 0;
617 }
618 else
619 {
620 }
621 }
622
623 if (interiorOnly == false )
624 {
625 for ( ossim_int32 idx = 0; idx < m_num; ++idx )
626 {
627 if ( new_counts[idx] == 0 ) new_counts[idx] = 1;
628 }
629 result->updateMinMax();
630 }
631
632 break;
633 }
634 }
635
636 return result;
637 }
638 //--------------------------------------------------
639 // -- Transform the value axis of a histogram by a
640 // translation, transl, and a scale factor, scale.
641 // The new histogram has the same resolution as his.
642
Scale(double scale_factor)643 ossimRefPtr<ossimHistogram> ossimHistogram::Scale(double scale_factor)
644 {
645
646 // Extract attributes of self
647
648 // double lowvalue = m_vals[0];
649 double highvalue = m_vals[m_num-1];
650
651 // Construct a new histogram
652
653 ossimRefPtr<ossimHistogram> scaled_his = new ossimHistogram(this, m_delta);
654 ossim_int64* new_counts = scaled_his->GetCounts();
655 int i = 0;
656 for(i=0; i < m_num; i++) // Initialize
657 new_counts[i] = 0;
658
659 // Compute scaled values
660 // We assume that the new histogram is to be scaled down from his
661
662 double scale = scale_factor;
663 if(scale_factor > 1.0) scale = 1.0;
664
665 for(double x = highvalue; x > m_vmin;)
666 {
667 double trans_x = (x-m_vmin)*scale + m_vmin; // Scaled x.
668 int index = GetIndex(trans_x);
669 if (index < 0)
670 {
671 if (trans_x<m_vmin) index = 0;
672 else index = m_num-1;
673 }
674 double fraction = (trans_x - m_vals[index])/m_delta;
675 double abs_fraction = (double)fabs(fraction);
676 int x_index = GetIndex(x);
677 if (x_index < 0)
678 {
679 if (x<m_vmin) x_index = 0;
680 else x_index = m_num-1;
681 }
682
683 // Distribute the m_counts in proportion
684
685 new_counts[index] += (1.0f - abs_fraction)*m_counts[x_index];
686 if(fraction > 0)
687 if(index < (m_num-1))
688 new_counts[index + 1] +=
689 abs_fraction*m_counts[x_index];
690 else
691 new_counts[index] +=
692 abs_fraction*m_counts[x_index];
693 else
694 if(index > 0)
695 new_counts[index - 1] +=
696 abs_fraction*m_counts[x_index];
697 else
698 new_counts[index] +=
699 abs_fraction*m_counts[x_index];
700 x -= m_delta;
701 }
702
703 // Compute new Histogram attributes
704
705 m_mean = scaled_his->GetMean();
706 m_standardDev = scaled_his->GetStandardDev();
707 return scaled_his;
708 }
709
710 //---------------------------------------------------------------------
711 // -- Assuming that "this" is a histogram of population density,
712 // construct a new histogram which is the cumulative distribution.
713 // Each bin, xi, in his is assumed to represent a density, i.e.,
714 // {x | (xi - .5*m_delta) < x <= (xi + .5*m_delta)}
715 // Each bin, xi, in the result represents a cumulative distribution, i.e.,
716 // {x | x <= (xi + .5*m_delta)}
CumulativeGreaterThanEqual() const717 ossimRefPtr<ossimHistogram> ossimHistogram::CumulativeGreaterThanEqual()const
718 {
719 ossimRefPtr<ossimHistogram> cum_his = new ossimHistogram(*this);
720 const ossim_int64* density_counts = this->GetCounts();
721 int res = this->GetRes();
722
723 // Intitialize cumulative m_counts
724 ossim_int64* cum_counts = cum_his->GetCounts();
725 int i = 0;
726 for(i=0; i < res; i++)
727 cum_counts[i] = 0;
728
729 cum_counts[res-1] = density_counts[res-1];
730 for(i = res-2; i>=0; --i)
731 {
732 cum_counts[i] += (density_counts[i] + cum_counts[i+1]);
733 }
734
735 return cum_his;
736 }
737
CumulativeLessThanEqual() const738 ossimRefPtr<ossimHistogram> ossimHistogram::CumulativeLessThanEqual()const
739 {
740 ossimHistogram* cum_his = new ossimHistogram(*this);
741 const ossim_int64* density_counts = this->GetCounts();
742 int res = this->GetRes();
743
744 // Intitialize cumulative m_counts
745 ossim_int64* cum_counts = cum_his->GetCounts();
746 int i = 0;
747 for(i=0; i < res; i++)
748 cum_counts[i] = 0;
749
750 cum_counts[0] = density_counts[0];
751 for(i = 1; i < res; i++)
752 {
753 cum_counts[i] += (density_counts[i] + cum_counts[i-1]);
754 }
755
756 return cum_his;
757 }
758
759 //Provides the correct values for histogram m_counts when the bin index
760 //extends outside the valid range of the m_counts array. This function
761 //permits easy array access logic for the NonMaximumSuppression algorithm.
762 //The cyclic flag indicates that the m_counts array index is circular, i.e,
763 //cnts[0] equivalent to cnts[n_bins-1]
GetExtendedCount(int bin,int n_bins,ossim_int64 * cnts,bool cyclic)764 inline double GetExtendedCount(int bin, int n_bins, ossim_int64* cnts, bool cyclic)
765 {
766 int nbm = n_bins-1;
767 if(!cyclic)
768 {
769 if(bin < 0)
770 return cnts[0];
771 if(bin >= n_bins)
772 return cnts[nbm];
773 }
774 else
775 {
776 if(bin<0)
777 return cnts[nbm+bin];
778 if(bin >= n_bins)
779 return cnts[bin-n_bins];
780 }
781 return cnts[bin];
782 }
783 //Prune any sequences of more than one maxium value
784 //That is, it is possible to have a "flat" top peak with an arbitarily
785 //long sequence of equal, but maximum values. The cyclic flag indictates
786 //that the sequence wraps around, i.e. cnts[0] equivalent to cnts[nbins-1]
RemoveFlatPeaks(int nbins,ossim_int64 * cnts,bool cyclic)787 inline void RemoveFlatPeaks(int nbins, ossim_int64* cnts, bool cyclic)
788 {
789 int nbm = nbins-1;
790
791 //Here we define a small state machine - parsing for runs of peaks
792 //init is the state corresponding to an initial run (starting at i ==0)
793 bool init=(GetExtendedCount(0, nbins, cnts, cyclic) !=0 ) ? true : false;
794 int init_end =0;
795
796 //start is the state corresponding to any other run of peaks
797 bool start=false;
798 int start_index=0;
799 int i = 0;
800
801 //The scan of the state machine
802 for(i = 0; i < nbins; i++)
803 {
804 double v = GetExtendedCount(i, nbins, cnts, cyclic);
805
806 //State init: a string of non-zeroes at the begining.
807 if(init&&v!=0)
808 continue;
809
810 if(init&&v==0)
811 {
812 init_end = i;
813 init = false;
814 continue;
815 }
816
817 //State !init&&!start: a string of "0s"
818 if(!start&&v==0)
819 continue;
820
821 //State !init&&start: the first non-zero value
822 if(!start&&v!=0)
823 {
824 start_index = i;
825 start = true;
826 continue;
827 }
828 //State ending flat peak: encountered a subsequent zero after starting
829 if(start&&v==0)
830 {
831 int peak_location = (start_index+i-1)/2;//The middle of the run
832 int k = 0;
833 for(k = start_index; k<=(i-1); k++)
834 if(k!=peak_location)
835 cnts[k] = 0;
836 start = false;
837 }
838 }
839 //Now handle the boundary conditions
840 //The non-cyclic case
841 if(!cyclic)
842 {
843 if(init_end!=0) //Was there an initial run of peaks?
844 {
845 int init_location = (init_end-1)/2;
846 int k = 0;
847 for(k = 0; k<init_end; k++)
848 if(k!=init_location)
849 cnts[k] = 0;
850 }
851 if(start) // Did we reach the end of the array in a run of pks?
852 {
853 int end_location = (start_index + nbm)/2;
854 int k = 0;
855 for(k = start_index; k<nbins; k++)
856 if(k!=end_location)
857 cnts[k] = 0;
858 }
859 }
860 else //The cyclic case
861 {
862 if(init_end!=0) //Is there a run which crosses the cyclic cut?
863 {
864 if(start)
865 { //Yes, so define the peak location accordingly
866 int peak_location = (start_index + init_end - nbm -1)/2;
867 int k;
868 if(peak_location < 0) //Is the peak to the left of the cut?
869 {// Yes, to the left
870 peak_location += nbm;
871 for( k = 0; k< init_end; k++)
872 cnts[k]=0;
873 for( k= start_index; k <nbins; k++)
874 if(k!=peak_location)
875 cnts[k] = 0;
876 }
877 else
878 {//No, on the right.
879 for( k = start_index; k< nbins; k++)
880 cnts[k]=0;
881 for( k= 0; k < init_end; k++)
882 if(k!=peak_location)
883 cnts[k] = 0;
884 }
885 }
886 else
887 {//There wasn't a final run so just clean up the initial run
888 int init_location = (init_end-1)/2;
889 int k = 0;
890 for(k = start_index; k<init_end; k++)
891 if(k!=init_location)
892 cnts[k] = 0;
893 }
894 }
895 }
896 }
897
898 //----------------------------------------------------------
899 // -- Suppress values in the Histogram which are not locally
900 // a maxium. The neighborhood for computing the local maximum
901 // is [radius X radius], e.g. for radius =1 the neighborhood
902 // is [-X-], for radius = 2, the neighborhood is [--X--], etc.
903 // If the cyclic flag is true then the index space is assumed to
904 // be equivalent to a circle. That is, elements "0" and (n_buckets-1)
905 // are in correspondence.
NonMaximumSupress(int radius,bool cyclic)906 ossimRefPtr<ossimHistogram> ossimHistogram::NonMaximumSupress(int radius, bool cyclic)
907 {
908 if((2*radius +1)> m_num/2)
909 {
910 ossimNotify(ossimNotifyLevel_WARN)<<"ossimHistogram::NonMaximumSupress the radius is too large \n";
911 return NULL;
912 }
913 //Get the m_counts array of "this"
914 ossimRefPtr<ossimHistogram> h_new = new ossimHistogram(*this);
915 int n_buckets = h_new->GetRes();
916 ossim_int64* counts_old = this->GetCounts();
917
918 //Make a new Histogram for the suppressed version
919 ossim_int64* counts_new = h_new->GetCounts();
920 int i;
921 for( i =0; i < n_buckets; i++)
922 counts_new[i] = 0;
923
924 //Find local maxima
925 for( i = 0; i< n_buckets; i++)
926 {
927 //find the maxium value in the current kernel
928 double max_count = counts_old[i];
929 int k = 0;
930 for(k = -radius; k <= radius ;k++)
931 {
932 int index = i+k;
933 double c = GetExtendedCount(index, n_buckets, counts_old, cyclic);
934 if( c > max_count)
935 max_count = c;
936 }
937 //Is position i a local maxium?
938 if(max_count == counts_old[i])
939 counts_new[i] = max_count;//Yes. So set the m_counts to the max value
940 }
941 RemoveFlatPeaks(n_buckets, counts_new, cyclic);
942 return h_new;
943 }
944 //----------------------------------------------------------
945 // -- Compute the m_mean of the histogram population
GetMean() const946 double ossimHistogram::GetMean()const
947 {
948 double xsum = 0.0;
949
950 if(MEAN_FLAG&m_statsConsistent)
951 return m_mean;
952 else
953 {
954 if( this->GetBucketSize() > 0.0){
955 for(double x=this->GetMinVal(); x<= this->GetMaxVal(); x +=this->GetBucketSize())
956 xsum += x*GetCount(x);
957 }
958
959 double area = ComputeArea(m_vmin, m_vmax);
960 if(area <= 0.0)
961 {
962 // fprintf(stderr, "Histogram : Area <= 0.0\n");
963 return 0.0;
964 }
965 else
966 {
967 m_statsConsistent |=1;
968 m_mean = xsum/area;
969 return m_mean;
970 }
971 }
972 }
973
974
975
GetStandardDev() const976 double ossimHistogram::GetStandardDev()const
977 {
978 double sum = 0.0;
979
980 if(SD_FLAG&m_statsConsistent)
981 return m_standardDev;
982 else
983 {
984 double xm = this -> GetMean(); // Force an Update of m_mean
985
986 if( this->GetBucketSize() > 0.0){
987 for(double x=this->GetMinVal();
988 x<= this->GetMaxVal();
989 x +=this->GetBucketSize())
990
991 sum += (x-xm)*(x-xm)*GetCount(x);
992 }
993
994 double area = ComputeArea(m_vmin, m_vmax);
995 if(area <= 0.0)
996 {
997 // fprintf(stderr, "Histogram : Area <= 0.0\n");
998 return 0.0;
999 }
1000 else
1001 {
1002 m_statsConsistent |= 2;
1003 m_standardDev = (double)sqrt(sum/area);
1004 return m_standardDev;
1005 }
1006 }
1007 }
1008
GetIndex(double pixelval) const1009 int ossimHistogram::GetIndex(double pixelval)const
1010 {
1011 #if 1
1012 if ((pixelval > m_vmax) || (pixelval < m_vmin) || (m_num==0) )
1013 {
1014 return -1;
1015 }
1016 // ossim_float64 d = m_vmax-m_vmin;
1017 int bandIdx = (ossim_int32)((pixelval-m_vmin)/m_delta);
1018 return bandIdx<m_num?bandIdx:-1;
1019 // if(bandIdx == m_num)
1020 // {
1021 // return m_num-1;
1022 // }
1023 // else if(bandIdx < m_num)
1024 // {
1025 // return bandIdx;
1026 // }
1027 // return -1;
1028 #else
1029 if ((pixelval > m_vmax) || (pixelval < m_vmin))
1030 return -1;
1031
1032 int idx = 0;
1033 int i = 0;
1034
1035 for(i = 0; i < m_num; i++)
1036 {
1037 //std::cout << std::setprecision(15) << m_vals[i] << std::endl;
1038 // RWMC: This is very dangerous - might get an intermediate
1039 // value which is between m_vals[i]+0.5*m_delta and
1040 // m_vals[i+1]-0.5*m_delta, which would then return index of 0.
1041 // Changed to check range one-sided, which is safe because of
1042 // previous check on range.
1043 // if ((pixelval > (m_vals[i] - 0.5 * m_delta)) &&
1044 // (pixelval <= (m_vals[i] + 0.5 * m_delta)))
1045 if (pixelval <= (m_vals[i] + 0.5 * m_delta))
1046 {
1047 idx = i;
1048 break;
1049 }
1050 }
1051 //std::cout << idx << std::endl;
1052 return idx;
1053 #endif
1054 }
GetMinValFromIndex(ossim_uint32 idx) const1055 double ossimHistogram::GetMinValFromIndex(ossim_uint32 idx)const
1056 {
1057 double result = 0.0;
1058
1059 if((int)idx < m_num)
1060 {
1061 result = (m_vals[idx]-(0.5 * m_delta));
1062 if(result < m_vmin) result = m_vmin;
1063 }
1064
1065 return result;
1066 }
1067
GetMaxValFromIndex(ossim_uint32 idx) const1068 double ossimHistogram::GetMaxValFromIndex(ossim_uint32 idx)const
1069 {
1070 double result = 0.0;
1071
1072 if((int)idx < m_num)
1073 {
1074 result = (m_vals[idx]+(0.5 * m_delta));
1075 if(result > m_vmax) result = m_vmax;
1076 }
1077
1078 return result;
1079 }
1080
GetValFromIndex(ossim_uint32 idx) const1081 double ossimHistogram::GetValFromIndex(ossim_uint32 idx)const
1082 {
1083 double result = 0.0;
1084 if((int)idx < m_num)
1085 {
1086 result = m_vals[idx];
1087 }
1088
1089 return result;
1090 }
1091
GetValIndex(double pixelval) const1092 int ossimHistogram::GetValIndex(double pixelval)const
1093 {
1094 int idx = -1;
1095 if ( (pixelval >= m_vmin) && (pixelval <= m_vmax) )
1096 {
1097 for(int i = 0; i < m_num; ++i)
1098 {
1099 if ((pixelval > (m_vals[i] - 0.5 * m_delta)) &&
1100 (pixelval <= (m_vals[i] + 0.5 * m_delta)))
1101 {
1102 idx = i;
1103 break;
1104 }
1105 }
1106 }
1107 return idx;
1108 }
1109
GetCount(double pixelval) const1110 double ossimHistogram::GetCount(double pixelval)const
1111 {
1112 int index = GetIndex(pixelval);
1113
1114 if (index < 0)
1115 return -1;
1116 else
1117 return m_counts[index];
1118 }
1119
GetMinVal() const1120 double ossimHistogram::GetMinVal()const
1121 {
1122 int i=0;
1123
1124 while (i<m_num-1 && !m_counts[i])
1125 i++;
1126
1127 return m_vals[i];
1128 }
1129
GetMaxVal() const1130 double ossimHistogram::GetMaxVal()const
1131 {
1132 int i=m_num-1;
1133
1134 while (i>0 && !m_counts[i])
1135 i--;
1136
1137 if (i < 0)
1138 return 0.0;
1139
1140 return m_vals[i];
1141 }
1142
1143
GetMaxCount() const1144 double ossimHistogram::GetMaxCount()const
1145 {
1146 int i=0;
1147 double max;
1148 max = 0.0;
1149 for (i=0; i < m_num; i++)
1150 if (m_counts[i] > max)
1151 max = m_counts[i];
1152 return max;
1153 }
1154
1155
1156
1157
SetCount(double pixelval,double count)1158 double ossimHistogram::SetCount(double pixelval, double count)
1159 {
1160 m_statsConsistent = 0;
1161
1162 int index = GetIndex(pixelval);
1163
1164 if (index < 0)
1165 return -1;
1166 else
1167 {
1168 m_counts[index] = count;
1169 return count;
1170 }
1171 }
1172
1173
UpCount(double pixelval,double occurences)1174 void ossimHistogram::UpCount(double pixelval, double occurences)
1175 {
1176
1177 m_statsConsistent = 0;
1178 int idx = GetIndex(pixelval);
1179 if (idx >= 0) // Originally (index > 0)
1180 {
1181 m_counts[idx] += (ossim_int64)occurences;
1182 }
1183 }
1184
ComputeArea(double low,double high) const1185 double ossimHistogram::ComputeArea(double low, double high)const
1186 {
1187 double sum = 0.0;
1188 double maxval = GetMaxVal();
1189 double minval = GetMinVal();
1190
1191 if (low < minval) low = minval;
1192 if (high > maxval) high = maxval;
1193
1194 if (low <= high)
1195 {
1196 int indexlow, indexhigh;
1197 indexlow = (int) GetIndex(low);
1198 if (indexlow < 0)
1199 {
1200 if (low<m_vmin) indexlow = 0;
1201 else indexlow = m_num-1;
1202 }
1203 indexhigh = (int) GetIndex(high);
1204 if (indexhigh < 0)
1205 {
1206 if (high<m_vmin) indexhigh = 0;
1207 else indexhigh = m_num-1;
1208 }
1209 int i=indexlow;
1210
1211 while (i<=indexhigh)
1212 {
1213 sum+= m_counts[i];
1214 i++;
1215 }
1216 }
1217
1218 return sum;
1219 }
1220 //----------------------------------------------------------------------
1221 // --Compute the total area under the histogram
1222 //
ComputeArea() const1223 double ossimHistogram::ComputeArea()const
1224 {
1225 double m_vmin = this->GetMinVal();
1226 double m_vmax = this->GetMaxVal();
1227 if(m_vmin>m_vmax)
1228 {
1229 double temp = m_vmin;
1230 m_vmin = m_vmax;
1231 m_vmax = temp;
1232 }
1233 return this->ComputeArea(m_vmin, m_vmax);
1234 }
1235
getLowFractionFromValue(double val) const1236 double ossimHistogram::getLowFractionFromValue(double val) const
1237 {
1238 ossim_float64 result = ossim::nan();
1239 int cutoff_bucket = GetValIndex(val);
1240 if ( cutoff_bucket > -1 )
1241 {
1242 int total_buckets = GetRes();
1243 double partial_sum = 0.0;
1244 double total_sum = 0.0;
1245 for(int i = 0; i < total_buckets; ++i)
1246 {
1247 total_sum += m_counts[i];
1248 if (i <= cutoff_bucket)
1249 {
1250 partial_sum += m_counts[i];
1251 }
1252 }
1253 result = partial_sum/total_sum;
1254 }
1255
1256 #if 0 /* Please leave for debug. */
1257 std::cout << "ossimHistogram::getLowFractionFromValue debug:\n"
1258 << "val: " << val
1259 << " cutoff_bucket" << cutoff_bucket
1260 << " result: " << result << "\n";
1261 #endif
1262
1263 return result;
1264 }
1265
getHighFractionFromValue(double val) const1266 double ossimHistogram::getHighFractionFromValue(double val) const
1267 {
1268 ossim_float64 result = ossim::nan();
1269 int cutoff_bucket = GetValIndex(val);
1270 if ( cutoff_bucket > -1 )
1271 {
1272 int total_buckets = GetRes();
1273 double partial_sum = 0.0;
1274 double total_sum = 0.0;
1275 for(int i = (total_buckets-1); i >= 0; --i)
1276 {
1277 total_sum += m_counts[i];
1278 if (i >= cutoff_bucket)
1279 {
1280 partial_sum += m_counts[i];
1281 }
1282 }
1283 result = partial_sum/total_sum;
1284 }
1285
1286 #if 0 /* Please leave for debug. */
1287 std::cout << "ossimHistogram::getHighFractionFromValue debug:\n"
1288 << "val: " << val
1289 << " cutoff_bucket" << cutoff_bucket
1290 << " result: " << result << "\n";
1291 #endif
1292
1293 return result;
1294 }
1295
1296 //----------------------------------------------------------------------
1297 // -- Finds the lower bound value which elminates a given fraction of
1298 // histogram area.
1299 //
LowClipVal(double clip_fraction) const1300 double ossimHistogram::LowClipVal(double clip_fraction)const
1301 {
1302 if(clip_fraction<0) clip_fraction=0.0;
1303 if(clip_fraction>1.0) clip_fraction=1.0;
1304 double area = this->ComputeArea();
1305 if(area==0.0) return this->GetMinVal();
1306 if(clip_fraction==0.0) return this->GetMinVal();
1307 if(clip_fraction==1.0) return this->GetMaxVal();
1308 double clip_area = area*clip_fraction;
1309 const ossim_int64* m_counts = this->GetCounts();
1310 const double* m_vals = this->GetVals();
1311 int res = this->GetRes();
1312 double sum = 0;
1313 int i=0;
1314
1315 for(; i<res; i++)
1316 {
1317 sum+=m_counts[i];
1318 if(sum>=clip_area)
1319 break;
1320 }
1321
1322 return m_vals[i];
1323 }
1324
1325 //----------------------------------------------------------------------
1326 // -- Finds the lower bound value which elminates a given fraction of
1327 // histogram area.
1328 //
HighClipVal(double clip_fraction) const1329 double ossimHistogram::HighClipVal(double clip_fraction)const
1330 {
1331 if(clip_fraction<0) clip_fraction=0.0;
1332 if(clip_fraction>1.0) clip_fraction=1.0;
1333 double area = this->ComputeArea();
1334 if(area==0.0) return this->GetMaxVal();
1335 if(clip_fraction==0.0) return this->GetMaxVal();
1336 if(clip_fraction==1.0) return this->GetMinVal();
1337 double clip_area = area*clip_fraction;
1338 const ossim_int64* m_counts = this->GetCounts();
1339 const double* m_vals = this->GetVals();
1340 int res = this->GetRes();
1341 double sum = 0;
1342 int i = (res-1);
1343 for(; i>=0; i--)
1344 {
1345 sum+=m_counts[i];
1346 if(sum>=clip_area)
1347 break;
1348 }
1349 return m_vals[i];
1350 }
1351
1352 //--------------------------------------------------------------------------
1353 // -- Prints histogram m_counts onto cout
Print() const1354 void ossimHistogram::Print()const
1355 {
1356 ostream& out = ossimNotify(ossimNotifyLevel_INFO);
1357 const double* m_vals = this->GetVals();
1358 const ossim_int64* m_counts = this->GetCounts();
1359 int res = this->GetRes();
1360 int width = 0;
1361 int i = 0;
1362 for(i =0; i < res; i++)
1363 {
1364 if(width++ > 5)
1365 {
1366 width = 0;
1367 out << "\n";
1368 }
1369 out << m_vals[i] << " " << m_counts[i] << " | " ;
1370 }
1371 out << "\n MaxVal " << this->GetMaxVal() << "\n"
1372 << " MinVal " << this->GetMinVal() << "\n"
1373 << " BucketSize " << this->GetBucketSize() << "\n"
1374 << " Resolution " << this->GetRes() << "\n"
1375 << " Area "
1376 << this->ComputeArea(this->GetMinVal(),this->GetMaxVal()) << "\n"
1377 << " Scalar type "
1378 << ossimScalarTypeLut::instance()->getEntryString( m_scalarType ).c_str()
1379 << "\n"
1380 << "------------------------------------------------\n\n";
1381 }
1382
1383 //---------------------------------------------------------------------------
1384 // --- dumps histogram values to file.
1385
Dump(char * dumpfile) const1386 void ossimHistogram::Dump(char *dumpfile)const
1387 {
1388 FILE *dumpfp = fopen(dumpfile, "w");
1389
1390 if (!dumpfp)
1391 {
1392 fprintf(stderr, "Error opening histogram data file.\n");
1393 return;
1394 }
1395 int i = 0;
1396
1397 for(i = 0; i < m_num; i++)
1398 fprintf(dumpfp, "%f %lld\n", m_vals[i], m_counts[i]);
1399
1400 fclose(dumpfp);
1401 return;
1402 }
1403
1404 //---------------------------------------------------------------------------
1405 // -- Writes histogram in format suitable for plotting tools like Gnuplot.
1406
WritePlot(const char * fname) const1407 int ossimHistogram::WritePlot(const char *fname)const
1408 {
1409 FILE *fp = fopen(fname, "w");
1410
1411 if (!fp)
1412 {
1413 fprintf(stderr, "Error opening histogram plot file.\n");
1414 return 0;
1415 }
1416
1417 for(int j = 0; j < m_num; j++)
1418 fprintf(fp, "%f %lld\n", m_vals[j], m_counts[j]);
1419
1420 fclose(fp);
1421 return 1;
1422 }
1423
deleteAll()1424 void ossimHistogram::deleteAll()
1425 {
1426 if (m_vals)
1427 {
1428 delete []m_vals;
1429 m_vals = NULL;
1430 }
1431 if (m_counts)
1432 {
1433 delete []m_counts;
1434 m_counts = NULL;
1435 }
1436 m_nullValue = ossim::nan();
1437 m_nullCount = 0;
1438 m_scalarType = OSSIM_SCALAR_UNKNOWN;
1439 }
1440
~ossimHistogram()1441 ossimHistogram::~ossimHistogram()
1442 {
1443 deleteAll();
1444 }
1445
1446
importHistogram(istream & in)1447 bool ossimHistogram::importHistogram(istream& in)
1448 {
1449 ossimProprietaryHeaderInformation header;
1450 bool binsCreated = false;
1451
1452 if(header.parseStream(in))
1453 {
1454 long numberOfBins = header.getNumberOfBins();
1455
1456 if(numberOfBins)
1457 {
1458 // create(numberOfBins, 0, numberOfBins - 1);
1459 create(numberOfBins, 0, numberOfBins - 1, m_nullValue, m_scalarType);
1460 binsCreated = true;
1461
1462 if(binsCreated)
1463 {
1464 ossimString buffer;
1465 ossimString binNumber;
1466 ossimString count;
1467
1468 while(in.good() &&
1469 !in.eof() &&
1470 *binNumber.c_str() != '.')
1471 {
1472
1473 getline(in, buffer);
1474
1475 istringstream s(buffer);
1476
1477 s >> binNumber >> count;
1478 if(*binNumber.c_str() != (char)'.')
1479 {
1480 SetCount((double)binNumber.toDouble(),
1481 (double)count.toDouble());
1482 }
1483 }
1484 }
1485 }
1486 else
1487 {
1488 return false;
1489 }
1490 }
1491 return true;
1492 }
1493
importHistogram(const ossimFilename & inputFile)1494 bool ossimHistogram::importHistogram(const ossimFilename& inputFile)
1495 {
1496 if(inputFile.exists())
1497 {
1498 ifstream input(inputFile.c_str());
1499
1500 return importHistogram(input);
1501 }
1502
1503 return false;
1504 }
1505
1506
parseStream(istream & in)1507 bool ossimHistogram::ossimProprietaryHeaderInformation::parseStream(istream& in)
1508 {
1509 ossimString inputLine;
1510
1511 getline(in, inputLine);
1512 if(inputLine.find("File Type") != string::npos)
1513 {
1514 std::string::size_type index = inputLine.find(":");
1515 if(index != std::string::npos)
1516 {
1517 m_fileType = inputLine.substr(index+1);
1518 m_fileType = m_fileType.trim();
1519 }
1520 else
1521 {
1522 return false;
1523 }
1524
1525 }
1526 else
1527 {
1528 return false;
1529 }
1530
1531 getline(in, inputLine);
1532 if(inputLine.find("Version") != string::npos)
1533 {
1534 std::string::size_type index = inputLine.find(":");
1535 if(index != std::string::npos)
1536 {
1537 m_version = inputLine.substr(index+1);
1538 m_version = m_version.trim();
1539 }
1540 else
1541 {
1542 return false;
1543 }
1544 }
1545 else
1546 {
1547 return false;
1548 }
1549
1550 getline(in, inputLine);
1551 if(inputLine.find("Mapper Type") != string::npos)
1552 {
1553 std::string::size_type index = inputLine.find(":");
1554 if(index != std::string::npos)
1555 {
1556 m_mapperType = inputLine.substr(index+1);
1557 m_mapperType = m_mapperType.trim();
1558 }
1559 else
1560 {
1561 return false;
1562 }
1563 }
1564 else
1565 {
1566 return false;
1567 }
1568
1569 getline(in, inputLine);
1570 if(inputLine.find("Number of Bins") != string::npos)
1571 {
1572 std::string::size_type index = inputLine.find(":");
1573 if(index != std::string::npos)
1574 {
1575 m_numberOfBins = inputLine.substr(index+1);
1576 m_numberOfBins = m_numberOfBins.trim();
1577 }
1578 else
1579 {
1580 return false;
1581 }
1582 }
1583 else
1584 {
1585 return false;
1586 }
1587
1588 return true;
1589 }
1590
saveState(ossimKeywordlist & kwl,const char * prefix) const1591 bool ossimHistogram::saveState(ossimKeywordlist& kwl,
1592 const char* prefix)const
1593 {
1594 kwl.add(prefix,
1595 "type",
1596 "ossimHistogram",
1597 true);
1598 kwl.add(prefix,
1599 "number_of_bins",
1600 m_num,
1601 true);
1602 kwl.add(prefix,
1603 "min_value",
1604 m_vmin,
1605 true);
1606 kwl.add(prefix,
1607 "max_value",
1608 m_vmax,
1609 true);
1610
1611 //---
1612 // Counting nulls not implemented completely so test and only save if
1613 // initialized.
1614 //---
1615 if ( ossim::isnan(m_nullValue) == false )
1616 {
1617 kwl.add(prefix,
1618 "null_value",
1619 m_nullValue,
1620 true);
1621 }
1622 if ( m_nullCount > 0 )
1623 {
1624 kwl.add(prefix,
1625 "null_count",
1626 m_nullCount,
1627 true);
1628 }
1629
1630 if ( m_scalarType != OSSIM_SCALAR_UNKNOWN )
1631 {
1632 kwl.add(prefix,
1633 "scalar_type",
1634 ossimScalarTypeLut::instance()->getEntryString( m_scalarType ).c_str(),
1635 true);
1636 }
1637
1638 ossimString binArrayList = "(";
1639 bool firstValue = true;
1640
1641 //---
1642 // If we know the scalar type, and it is an interger, use the form of
1643 // "(pixel_value,count)"; if not, then use "(bin_index,count)".
1644 // Note "bin_index" may or may not be the same as the pixel value.
1645 //---
1646 if ( ossim::isInteger( m_scalarType ) )
1647 {
1648 ossim_int32 pixelValue = 0;
1649 ossim_int64 count = 0;
1650 for(ossim_int32 index = 0; index < m_num; ++index)
1651 {
1652 if( m_counts[index] > 0 )
1653 {
1654 if(!firstValue)
1655 {
1656 binArrayList += ",";
1657 }
1658 else
1659 {
1660 firstValue = false;
1661 }
1662 pixelValue = GetValFromIndex( index );
1663 count = m_counts[index];
1664 binArrayList += "("+ossimString::toString(pixelValue)+","
1665 +ossimString::toString(count)+")";
1666 }
1667 }
1668 }
1669 else
1670 {
1671 ossim_int64 count = 0;
1672 for(ossim_int32 index = 0; index < m_num; ++index)
1673 {
1674 if( m_counts[index] > 0 )
1675 {
1676 if(!firstValue)
1677 {
1678 binArrayList += ",";
1679 }
1680 else
1681 {
1682 firstValue = false;
1683 }
1684 count = m_counts[index];
1685 binArrayList += "("+ossimString::toString(index)+","
1686 +ossimString::toString(count)+")";
1687 }
1688 }
1689 }
1690
1691 binArrayList += ")";
1692
1693 kwl.add(prefix, "bins", binArrayList, true);
1694
1695 return true;
1696 }
1697
loadState(const ossimKeywordlist & kwl,const char * prefix)1698 bool ossimHistogram::loadState(const ossimKeywordlist& kwl,
1699 const char* prefix)
1700 {
1701 // std::cout << "ossimHistogram::loadState!!!!\n";
1702 const char* number_of_bins = kwl.find(prefix, "number_of_bins");
1703
1704 // std::cout << "NBINS = " << number_of_bins << std::endl;
1705
1706 if(number_of_bins)
1707 {
1708 ossim_uint32 bins = ossimString(number_of_bins).toUInt32();
1709
1710 // std::cout << "BINS ======== " << bins << std::endl;
1711 if(bins > 0)
1712 {
1713 // setup some defaults
1714 double minValue = 0;
1715 double maxValue = bins - 1;
1716
1717 // see if there is a range set for the data
1718 const char* min_value = kwl.find(prefix, "min_value");
1719 const char* max_value = kwl.find(prefix, "max_value");
1720 if(min_value)
1721 {
1722 minValue = (ossim_float64)ossimString(min_value).toDouble();
1723 }
1724 if(max_value)
1725 {
1726 maxValue = (ossim_float64)ossimString(max_value).toDouble();
1727 }
1728
1729 // Must do null stuff after create.
1730 const char* null_value = kwl.find(prefix, "null_value");
1731 const char* null_count = kwl.find(prefix, "null_count");
1732 if(null_value)
1733 {
1734 m_nullValue = ossimString(null_value).toDouble();
1735 }
1736 if(null_count)
1737 {
1738 m_nullCount = ossimString(null_count).toUInt64();
1739 }
1740
1741 //---
1742 // If "scalar_type" is set(in histogram file) and and of integer type,
1743 // then the histogram should be in the form of "(pixel_value,count)";
1744 // if not, it should be "(bin_index,count)" where "bin_index" may or
1745 // may not be the same as the pixel value.
1746 //---
1747 const char* scalar_type = kwl.find(prefix, "scalar_type");
1748 bool indexesArePixelValues = false;
1749 if ( scalar_type )
1750 {
1751 m_scalarType = ossimScalarTypeLut::instance()->getScalarTypeFromString(scalar_type);
1752 indexesArePixelValues = ossim::isInteger( m_scalarType );
1753 }
1754
1755 create((int)bins, minValue, maxValue, m_nullValue, m_scalarType);
1756
1757 ossim_int64* countsPtr = GetCounts();
1758 memset(countsPtr, '\0', bins*sizeof(ossim_int64));
1759
1760 ossimString binsString = kwl.find(prefix, "bins");
1761 if(!binsString.empty())
1762 {
1763 std::vector<ossimDpt> result;
1764 ossim::toVector(result, binsString);
1765 if(!result.empty())
1766 {
1767 ossim_int32 idx = 0;
1768 ossim_int32 binIdx = 0;
1769 if ( indexesArePixelValues )
1770 {
1771 for(idx = 0; idx < (ossim_int32)result.size();++idx)
1772 {
1773 // Get index from pixel value.
1774 binIdx = GetIndex( (double)result[idx].x );
1775 if( (binIdx >= 0) && (binIdx < (ossim_int32)bins) )
1776 {
1777 countsPtr[binIdx] = result[idx].y;
1778 }
1779 }
1780 }
1781 else
1782 {
1783 for(idx = 0; idx < (ossim_int32)result.size();++idx)
1784 {
1785 binIdx = static_cast<ossim_int32>(result[idx].x);
1786 if( (binIdx >= 0) && (binIdx < (ossim_int32)bins) )
1787 {
1788 countsPtr[binIdx] = result[idx].y;
1789 }
1790 }
1791 }
1792 }
1793 }
1794 else
1795 {
1796 ossimKeywordlist binsKwl;
1797 ossim_uint32 offset = (ossim_uint32)(ossimString(prefix)+"bin").size();
1798 ossimString regExpression = ossimString("^(") + ossimString(prefix) + "bin[0-9]+)";
1799 kwl.extractKeysThatMatch(binsKwl,regExpression);
1800 const ossimKeywordlist::KeywordMap& kwlMap = binsKwl.getMap();
1801 ossimKeywordlist::KeywordMap::const_iterator iter = kwlMap.begin();
1802 while(iter != kwlMap.end())
1803 {
1804 ossimString numberStr(iter->first.begin() + offset,
1805 iter->first.end());
1806 countsPtr[numberStr.toUInt32()] = ossimString(iter->second).toDouble();
1807 ++iter;
1808 }
1809 }
1810
1811 // ossimKeywordlist kwl;
1812 // this->saveState(kwl);
1813 // std::cout << kwl << std::endl;
1814
1815 return true;
1816 #if 0
1817 // create the bins
1818 ossimString binNumber = "";
1819 ossimString regExpression = ossimString("^(") + ossimString(prefix) + "bin[0-9]+)";
1820 vector<ossimString> keys = kwl.getSubstringKeyList( regExpression );
1821 ossim_uint32 numberOfBins = (ossim_uint32)keys.size();
1822 ossim_uint32 offset = (ossim_uint32)(ossimString(prefix)+"bin").size();
1823
1824 std::vector<ossim_uint32> theNumberList(numberOfBins);
1825 ossim_uint32 idx = 0;
1826 for(idx = 0; idx < theNumberList.size();++idx)
1827 {
1828 ossimString numberStr(keys[idx].begin() + offset,
1829 keys[idx].end());
1830 theNumberList[idx] = numberStr.toUInt32();
1831
1832 }
1833
1834 double* countsPtr = GetCounts();
1835 memset(countsPtr, '\0', bins*sizeof(double));
1836 for(idx = 0; idx < numberOfBins;++idx)
1837 {
1838 const char* binCount = kwl.find(prefix, ossimString("bin") + ossimString::toString(theNumberList[idx]));
1839 countsPtr[theNumberList[idx]] = (double)ossimString(binCount).toDouble();
1840 }
1841 #endif
1842 }
1843 }
1844 return true;
1845 }
1846
loadState(const ossimRefPtr<ossimXmlNode> xmlNode)1847 bool ossimHistogram::loadState(const ossimRefPtr<ossimXmlNode> xmlNode)
1848 {
1849 ossimRefPtr<ossimXmlNode> binValues = xmlNode->findFirstNode("binValues");
1850 ossimRefPtr<ossimXmlNode> minValueNode = xmlNode->findFirstNode("minValue");
1851 ossimRefPtr<ossimXmlNode> maxValueNode = xmlNode->findFirstNode("maxValue");
1852
1853 if(binValues.valid())
1854 {
1855 ossim_uint32 count = 0;
1856 double minValue = 0.0;
1857 double maxValue = 0.0;
1858 std::vector<double> doubleValues;
1859 std::istringstream in(binValues->getText());
1860 ossimString vString;
1861 while(!in.fail())
1862 {
1863 in>>vString;
1864 if(!in.fail())
1865 {
1866 doubleValues.push_back(vString.toFloat64());
1867 }
1868 }
1869 count = (ossim_uint32)doubleValues.size();
1870
1871 if(count)
1872 {
1873 minValue = 0;
1874 maxValue = count - 1;
1875
1876 if(minValueNode.valid())
1877 {
1878 minValue = minValueNode->getText().toFloat64();
1879 }
1880 if(maxValueNode.valid())
1881 {
1882 maxValue = maxValueNode->getText().toFloat64();
1883 }
1884
1885 // Fix to add/get null and scalar from xml.
1886 create(count, minValue, maxValue, m_nullValue, m_scalarType);
1887 ossim_int64* countsPtr = GetCounts();
1888 ossim_uint32 idx = 0;
1889 for(idx = 0; idx < count; ++idx)
1890 {
1891 countsPtr[idx] = (ossim_int64)doubleValues[idx];
1892 }
1893 return true;
1894 }
1895 }
1896
1897 return false;
1898 }
1899
saveState(ossimRefPtr<ossimXmlNode> xmlNode) const1900 bool ossimHistogram::saveState(ossimRefPtr<ossimXmlNode> xmlNode)const
1901 {
1902 ossimRefPtr<ossimXmlNode> binValues = new ossimXmlNode;
1903 xmlNode->setTag("ossimHistogram");
1904 xmlNode->addChildNode("minValue", ossimString::toString(m_vmin));
1905 xmlNode->addChildNode("maxValue", ossimString::toString(m_vmax));
1906 xmlNode->addChildNode("standardDeviation", ossimString::toString(m_standardDev));
1907 xmlNode->addChildNode("m_mean", ossimString::toString(m_mean));
1908 binValues->setTag("binValues");
1909 std::ostringstream out;
1910
1911 ossim_int32 idx = 0;
1912 if(m_num > 0)
1913 {
1914 for(idx = 0; idx < m_num;++idx)
1915 {
1916 out << ossimString::toString(m_counts[idx]) << " ";
1917 }
1918 binValues->setText(out.str());
1919 }
1920 xmlNode->addChildNode(binValues.get());
1921
1922 return true;
1923 }
1924
1925
getScalarType() const1926 ossimScalarType ossimHistogram::getScalarType() const
1927 {
1928 return m_scalarType;
1929 }
1930
setScalarType(ossimScalarType scalar)1931 void ossimHistogram::setScalarType( ossimScalarType scalar )
1932 {
1933 m_scalarType = scalar;
1934 }
1935
getNullValue() const1936 const double& ossimHistogram::getNullValue() const
1937 {
1938 return m_nullValue;
1939 }
1940
setNullValue(const double & nullValue)1941 void ossimHistogram::setNullValue(const double& nullValue)
1942 {
1943 m_nullValue = nullValue;
1944 }
1945
getNullCount() const1946 const ossim_uint64& ossimHistogram::getNullCount() const
1947 {
1948 return m_nullCount;
1949 }
1950
upNullCount(const ossim_uint64 & count)1951 void ossimHistogram::upNullCount( const ossim_uint64& count )
1952 {
1953 m_nullCount += count;
1954 }
1955
updateMinMax()1956 void ossimHistogram::updateMinMax()
1957 {
1958 m_vmin = GetMinVal();
1959 m_vmax = GetMaxVal();
1960 }
1961