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