1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #include "itkMath.h"
20 #include "itkHistogram.h"
21 #include "itkSample.h"
22 #include "itkTestingMacros.h"
23 
itkHistogramTest(int,char * [])24 int itkHistogramTest( int, char* [] )
25 {
26   std::cout << "Histogram Test \n \n";
27   bool pass = true;
28   std::string whereFail = "";
29 
30   using MeasurementType = float;
31   constexpr unsigned int numberOfComponents = 3;
32 
33   // create a histogram with 3 components measurement vectors
34   using HistogramType = itk::Statistics::Histogram< MeasurementType,
35           itk::Statistics::DenseFrequencyContainer2 >;
36   HistogramType::Pointer histogram = HistogramType::New();
37 
38   EXERCISE_BASIC_OBJECT_METHODS( histogram, Histogram, Sample );
39 
40   using MeasurementVectorType = HistogramType::MeasurementVectorType;
41   using InstanceIdentifier = HistogramType::InstanceIdentifier;
42   using IndexType = HistogramType::IndexType;
43 
44   // initializes a 64 x 64 x 64 histogram with equal size interval
45   HistogramType::SizeType size( numberOfComponents );
46   size.Fill(64);
47   unsigned long totalSize = size[0] * size[1] * size[2];
48 
49   MeasurementVectorType lowerBound( numberOfComponents );
50   MeasurementVectorType upperBound( numberOfComponents );
51 
52   lowerBound.Fill(0);
53   upperBound.Fill(1024);
54 
55   //
56   // Exercise exception case
57   //
58   try
59     {
60     // purposely calling Initialize() before calling SetMeasurementVectorSize()
61     // in order to trigger an expected exception.
62     histogram->Initialize(size);
63     pass = false;
64     whereFail = "Initialize(size) before SetMeasurementVectorSize() didn't throw expected exception";
65     }
66   catch( itk::ExceptionObject & excp )
67     {
68     std::cout << "Expected exception ";
69     std::cout << excp << std::endl;
70     }
71 
72 
73   //
74   // Now call SetMeasurementVectorSize() correctly
75   //
76   histogram->SetMeasurementVectorSize( numberOfComponents );
77 
78   if( histogram->GetMeasurementVectorSize() != numberOfComponents )
79     {
80     std::cerr << "Error in Get/SetMeasurementVectorSize() " << std::endl;
81     return EXIT_FAILURE;
82     }
83 
84   //
85   //  Exercise Initialize with size and bounds
86   //
87   histogram->Initialize(size, lowerBound, upperBound );
88 
89   histogram->SetToZero();
90 
91   double interval =
92     (upperBound[0] - lowerBound[0]) /
93     static_cast< HistogramType::MeasurementType >(size[0]);
94 
95   // tests begin
96   MeasurementVectorType measurements( numberOfComponents );
97   measurements.Fill(512);
98 
99   IndexType index( numberOfComponents );
100   IndexType ind( numberOfComponents );
101   index.Fill(32);
102   if(histogram->GetIndex(measurements,ind))
103     {
104     if(index != ind)
105       {
106       pass = false;
107       whereFail = "GetIndex(MeasurementVectorType&)";
108       }
109     }
110   else
111     {
112     pass = false;
113     whereFail = "GetIndex(MeasurementVectorType&)";
114     }
115 
116   InstanceIdentifier id = histogram->GetInstanceIdentifier(index);
117   if (index != histogram->GetIndex(id))
118     {
119     pass = false;
120     whereFail = "GetIndex(InstanceIdentifier&)";
121     }
122 
123   index.Fill( -5 ); // test for outside below
124 
125   if( !histogram->IsIndexOutOfBounds(index) )
126     {
127     std::cerr << "IsIndexOutOfBounds() for " << index << std::endl;
128     pass = false;
129     whereFail = "IsIndexOutOfBounds(IndexType)";
130     }
131 
132 
133   index.Fill(32); // test for inside
134 
135   if( histogram->IsIndexOutOfBounds(index) )
136     {
137     std::cerr << "IsIndexOutOfBounds() for " << index << std::endl;
138     pass = false;
139     whereFail = "IsIndexOutOfBounds(IndexType)";
140     }
141 
142   index.Fill(100); // test for outside
143 
144   if( !histogram->IsIndexOutOfBounds(index) )
145     {
146     std::cerr << "IsIndexOutOfBounds() for " << index << std::endl;
147     pass = false;
148     whereFail = "IsIndexOutOfBounds(IndexType)";
149     }
150 
151   if (totalSize != histogram->Size())
152     {
153     pass = false;
154     whereFail = "Size()";
155     }
156 
157   if (size != histogram->GetSize())
158     {
159     pass = false;
160     whereFail = "GetSize()";
161     }
162 
163   // Query the bounds of the bin using the index of the bin.
164 
165   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 31), histogram->GetBinMin(0,31) ))
166     {
167     pass = false;
168     whereFail = "GetBinMin(Dimension, nthBin)";
169     }
170 
171   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 32), histogram->GetBinMax(0,31) ))
172     {
173     pass = false;
174     whereFail = "GetBinMax(Dimension, nthBin)";
175     }
176 
177   // Query the histogram bin extremes using a value within the bin
178 
179   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 31         ), histogram->GetBinMinFromValue(0, lowerBound[0] + interval * 31.5 ) )
180    || itk::Math::NotAlmostEquals( (lowerBound[0]                         ), histogram->GetBinMinFromValue(0, itk::NumericTraits< float >::min()   ) )
181    || itk::Math::NotAlmostEquals( (lowerBound[0] + interval * (size[0]-1)), histogram->GetBinMinFromValue(0, itk::NumericTraits< float >::max() ) ) )
182     {
183     pass = false;
184     whereFail = "GetBinMinFromValue(Dimension, A Value Within The Nth Bin)";
185     }
186 
187   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 32         ), histogram->GetBinMaxFromValue(0, lowerBound[0] + interval * 31.5 ) )
188    || itk::Math::NotAlmostEquals( (lowerBound[0] + interval              ), histogram->GetBinMaxFromValue(0, itk::NumericTraits< float >::min()   ) )
189    || itk::Math::NotAlmostEquals( (upperBound[0]                         ), histogram->GetBinMaxFromValue(0, itk::NumericTraits< float >::max() ) ) )
190     {
191     pass = false;
192     whereFail = "GetBinMaxFromValue(Dimension, A Value Within The Nth Bin)";
193     }
194 
195   index.Fill(31);
196   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 31), histogram->GetHistogramMinFromIndex(index)[0]) )
197     {
198     pass = false;
199     whereFail = "GetHistogramMinFromIndex(Dimension, nthBin)";
200     }
201 
202   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 32), histogram->GetHistogramMaxFromIndex(index)[0]) )
203     {
204     pass = false;
205     whereFail = "GetHistogramMaxFromIndex(Dimension, nthBin)";
206     }
207 
208   for (id = 0;
209        id < static_cast< InstanceIdentifier >(totalSize);
210        id++)
211     {
212     histogram->SetFrequency(id, 1);
213     histogram->IncreaseFrequency(id, 1);
214     if (histogram->GetFrequency(id) != 2)
215       {
216       pass = false;
217       whereFail =
218         "SetFrequency(InstanceIdentifier, 1) + IncreaseFrequency(InstanceIdentifier, 1) + GetFrequency(InstanceIdentifier)";
219       }
220     }
221 
222   double quantile1 = histogram->Quantile(0, 0.3);
223   if( itk::Math::NotAlmostEquals( quantile1, 307.2) )
224     {
225     std::cerr << "quantile1 = " << quantile1 << std::endl;
226     pass = false;
227     whereFail = "Quantile(Dimension, percent)";
228     }
229 
230   double quantile2 = histogram->Quantile(0, 0.5);
231   if( quantile2 != 512.0)
232     {
233     std::cerr << "quantile2 = " << quantile2 << std::endl;
234     pass = false;
235     whereFail = "Quantile(Dimension, percent)";
236     }
237 
238   double quantile3 = histogram->Quantile(0, 0.7);
239   if( itk::Math::NotAlmostEquals( quantile3, 716.8) )
240     {
241     std::cerr << "quantile3 = " << quantile3 << std::endl;
242     pass = false;
243     whereFail = "Quantile(Dimension, percent)";
244     }
245 
246 
247   if( !pass )
248     {
249     std::cerr << "Test failed in " << whereFail << "." << std::endl;
250     return EXIT_FAILURE;
251     }
252 
253 
254   // Histogram with SparseFrequencyContainer2
255   using SparseHistogramType = itk::Statistics::Histogram< MeasurementType,
256     itk::Statistics::SparseFrequencyContainer2 >;
257   SparseHistogramType::Pointer sparseHistogram = SparseHistogramType::New();
258 
259   sparseHistogram->SetMeasurementVectorSize( numberOfComponents );
260 
261   // initializes a 64 x 64 x 64 histogram with equal size interval
262   sparseHistogram->Initialize(size, lowerBound, upperBound );
263   sparseHistogram->SetToZero();
264   interval = (upperBound[0] - lowerBound[0]) /
265     static_cast< SparseHistogramType::MeasurementType >(size[0]);
266 
267   measurements.Fill(512);
268   index.Fill(32);
269   sparseHistogram->GetIndex(measurements,ind);
270 
271   if (index != ind)
272     {
273     pass = false;
274     whereFail = "Sparse Histogram: GetIndex(MeasurementVectorType&)";
275     }
276 
277   id = sparseHistogram->GetInstanceIdentifier(index);
278   if (index != sparseHistogram->GetIndex(id))
279     {
280     pass = false;
281     whereFail = "Sparse Histogram: GetIndex(InstanceIdentifier&)";
282     }
283 
284   index.Fill(100);
285 
286   if (!sparseHistogram->IsIndexOutOfBounds(index))
287     {
288     pass = false;
289     whereFail = "Sparse Histogram: IsIndexOutOfBounds(IndexType)";
290     }
291 
292   if (totalSize != sparseHistogram->Size())
293     {
294     pass = false;
295     whereFail = "Sparse Histogram: Size()";
296     }
297 
298   if (size != sparseHistogram->GetSize())
299     {
300     pass = false;
301     whereFail = "Sparse Histogram: GetSize()";
302     }
303 
304   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 31), sparseHistogram->GetBinMin(0,31) ))
305     {
306     pass = false;
307     whereFail = "Sparse Histogram: GetBinMin(Dimension, nthBin)";
308     }
309 
310   if (itk::Math::NotAlmostEquals( (lowerBound[0] + interval * 32), sparseHistogram->GetBinMax(0,31) ))
311     {
312     pass = false;
313     whereFail = "Sparse Histogram: GetBinMax(Dimension, nthBin)";
314     }
315 
316 
317   for (id = 0;
318        id < static_cast< SparseHistogramType::InstanceIdentifier >(totalSize);
319        id++)
320     {
321     bool result = sparseHistogram->SetFrequency(id, 1);
322     if( !result )
323       {
324       pass = false;
325       whereFail =
326         "SetFrequency(InstanceIdentifier, 1) ";
327       break;
328 
329       }
330 
331     result = sparseHistogram->IncreaseFrequency(id, 1);
332     if( !result )
333       {
334       pass = false;
335       whereFail =
336         "IncreaseFrequency(InstanceIdentifier, 1) ";
337       break;
338       }
339 
340     if (sparseHistogram->GetFrequency(id) != 2)
341       {
342       pass = false;
343       whereFail =
344         "SetFrequency(InstanceIdentifier, 1) + IncreaseFrequency(InstanceIdentifier, 1) + GetFrequency(InstanceIdentifier)";
345       break;
346       }
347     }
348 
349   if (pass && (sparseHistogram->Quantile(0, 0.5) != 512.0))
350     {
351     pass = false;
352     whereFail = "Sparse Histogram: Quantile(Dimension, percent)";
353     }
354 
355 
356   histogram->SetClipBinsAtEnds( true );
357   if( !histogram->GetClipBinsAtEnds() )
358     {
359     pass = false;
360     whereFail = "Set/GetClipBinsAtEnds()";
361     }
362 
363   histogram->SetClipBinsAtEnds( false );
364   if( histogram->GetClipBinsAtEnds() )
365     {
366     pass = false;
367     whereFail = "Set/GetClipBinsAtEnds()";
368     }
369 
370   if( histogram->GetMeasurementVectorSize() != numberOfComponents )
371     {
372     pass = false;
373     whereFail = "Set/GetMeasurementVectorSize()";
374     }
375 
376   constexpr unsigned int measurementVectorSize = 17;
377 
378   try
379     {
380     histogram->SetMeasurementVectorSize( measurementVectorSize );
381     pass = false;
382     whereFail = "SetMeasurementVectorSize() didn't throw expected exception";
383     }
384   catch( itk::ExceptionObject & excp )
385     {
386     std::cout << "Expected exception ";
387     std::cout << excp << std::endl;
388     }
389 
390   index.Fill(0);
391   MeasurementVectorType measurement = histogram->GetMeasurementVector( index );
392   for( unsigned kid0 = 0; kid0 < numberOfComponents; kid0++ )
393     {
394     if( itk::Math::NotAlmostEquals( measurement[kid0], 8 ))
395       {
396       std::cerr << "GetMeasurementVector() for index = ";
397       std::cerr << index << std::endl;
398       pass = false;
399       whereFail = "GetMeasurementVector() failed for index";
400       break;
401       }
402     }
403 
404   histogram->SetClipBinsAtEnds( true );
405 
406   measurement = histogram->GetMeasurementVector( index );
407   for( unsigned kid1 = 0; kid1 < numberOfComponents; kid1++ )
408     {
409     if( itk::Math::NotAlmostEquals( measurement[kid1], 8 ) )
410       {
411       std::cerr << "GetMeasurementVector() for index = ";
412       std::cerr << index << std::endl;
413       pass = false;
414       whereFail = "GetMeasurementVector() failed for index";
415       break;
416       }
417     }
418 
419   constexpr InstanceIdentifier instanceId  = 0;
420   measurement = histogram->GetMeasurementVector( instanceId );
421   for( unsigned kid2 = 0; kid2 < numberOfComponents; kid2++ )
422     {
423     if( itk::Math::NotAlmostEquals( measurement[kid2], 8 ) )
424       {
425       std::cerr << "GetMeasurementVector() for instanceId = ";
426       std::cerr << instanceId << std::endl;
427       pass = false;
428       whereFail = "GetMeasurementVector() failed for instanceId";
429       break;
430       }
431     }
432 
433   // Test GetIndex with different settings of SetClipBinsAtEnds
434   MeasurementVectorType outOfLowerRange( numberOfComponents );
435   MeasurementVectorType outOfUpperRange( numberOfComponents );
436 
437   for(unsigned int k = 0; k < numberOfComponents; k++)
438     {
439     outOfLowerRange[k] = lowerBound[k] - 13;
440     outOfUpperRange[k] = upperBound[k] + 23;
441     }
442 
443   histogram->SetClipBinsAtEnds( false );
444 
445   IndexType index1( numberOfComponents );
446   bool getindex1 = histogram->GetIndex( outOfLowerRange, index1 );
447 
448   std::cout << "GetIndex() with SetClipBinsAtEnds() = false " << std::endl;
449   std::cout << "Boolean " << getindex1 << " Index " << index1 << std::endl;
450 
451   if( !getindex1 )
452     {
453     pass = false;
454     whereFail = "GetIndex() returned boolean failed for outOfLowerRange";
455     }
456 
457   for(unsigned k1=0; k1 < numberOfComponents; k1++ )
458     {
459     if( index1[ k1 ] != 0 )
460       {
461       pass = false;
462       whereFail = "GetIndex() index value failed for outOfLowerRange";
463       }
464     }
465 
466 
467   histogram->SetClipBinsAtEnds( true );
468 
469   getindex1 = histogram->GetIndex( outOfLowerRange, index1 );
470 
471   std::cout << "GetIndex() with SetClipBinsAtEnds() = true " << std::endl;
472   std::cout << "Boolean " << getindex1 << " Index " << index1 << std::endl;
473 
474   if( getindex1 )
475     {
476     pass = false;
477     whereFail = "GetIndex() failed for outOfLowerRange";
478     }
479 
480   histogram->SetClipBinsAtEnds( false );
481 
482   IndexType index2( numberOfComponents );
483   bool getindex2 = histogram->GetIndex( outOfUpperRange, index2 );
484 
485   std::cout << "GetIndex() with SetClipBinsAtEnds() = false " << std::endl;
486   std::cout << "Boolean " << getindex2 << " Index " << index2 << std::endl;
487 
488   if( !getindex2 )
489     {
490     pass = false;
491     whereFail = "GetIndex() returned boolean failed for outOfUpperRange";
492     }
493 
494   for(unsigned k2=0; k2 < numberOfComponents; k2++ )
495     {
496     if( index2[ k2 ] != (long)size[k2] - 1 )
497       {
498       pass = false;
499       whereFail = "GetIndex() index value failed for outOfUpperRange";
500       }
501     }
502 
503 
504   histogram->SetClipBinsAtEnds( true );
505 
506   getindex2 = histogram->GetIndex( outOfUpperRange, index2 );
507 
508   std::cout << "GetIndex() with SetClipBinsAtEnds() = true " << std::endl;
509   std::cout << "Boolean " << getindex2 << " Index " << index2 << std::endl;
510 
511   if( getindex2 )
512     {
513     pass = false;
514     whereFail = "GetIndex() failed for outOfUpperRange";
515     }
516 
517 
518   // Testing GetIndex() for values that are above the median value of the Bin.
519   IndexType pindex( numberOfComponents );
520   pindex.Fill( 32 );
521   MeasurementVectorType measurementVector =
522     histogram->GetMeasurementVector( pindex );
523 
524   for( unsigned int gik1=0; gik1<numberOfComponents; gik1++)
525     {
526     measurementVector[gik1] += 0.3;
527     }
528 
529   IndexType gindex;
530   histogram->GetIndex( measurementVector, gindex );
531 
532   for( unsigned int gik2=0; gik2<numberOfComponents; gik2++)
533     {
534     if( gindex[gik2] != 32 )
535       {
536       std::cerr << "GetIndex() / GetMeasurementVector() failed " << std::endl;
537       std::cerr << "MeasurementVector = " << measurementVector << std::endl;
538       std::cerr << "Index returned = " << gindex << std::endl;
539       return EXIT_FAILURE;
540       }
541     }
542 
543   // Testing GetIndex() for values that are below the median value of the Bin.
544   for( unsigned int gik3=0; gik3<numberOfComponents; gik3++)
545     {
546     measurementVector[gik3] -= 0.6;
547     }
548 
549   histogram->GetIndex( measurementVector ,gindex);
550 
551   for( unsigned int gik4=0; gik4<numberOfComponents; gik4++)
552     {
553     if( gindex[gik4] != 32 )
554       {
555       std::cerr << "GetIndex() / GetMeasurementVector() failed " << std::endl;
556       std::cerr << "MeasurementVector = " << measurementVector << std::endl;
557       std::cerr << "Index returned = " << gindex << std::endl;
558       return EXIT_FAILURE;
559       }
560     }
561 
562   // Testing GetIndex on the upper and lower bounds
563   IndexType upperIndex( numberOfComponents );
564   bool upperIndexBool = histogram->GetIndex( upperBound, upperIndex );
565   if( !upperIndexBool )
566     {
567     pass = false;
568     whereFail = "GetIndex() returned boolean failed for upper bound";
569     }
570 
571   for(unsigned k1=0; k1 < numberOfComponents; k1++ )
572     {
573     if( upperIndex[ k1 ] != 63 )
574       {
575       pass = false;
576       whereFail = "GetIndex() index value failed for upperBound, as upper bound should map to the last bin.";
577       }
578     }
579 
580   IndexType lowerIndex( numberOfComponents );
581   bool lowerIndexBool = histogram->GetIndex( lowerBound, lowerIndex );
582   if( !lowerIndexBool )
583     {
584     pass = false;
585     whereFail = "GetIndex() returned boolean failed for lower bound";
586     }
587 
588   for(unsigned k1=0; k1 < numberOfComponents; k1++ )
589     {
590     if( lowerIndex[ k1 ] != 0 )
591       {
592       pass = false;
593       whereFail = "GetIndex() index value failed for lowerIndex, as lower bound should map to the first bin.";
594       }
595     }
596 
597   // Testing GetIndex above the upper bound of a bin
598   histogram->SetClipBinsAtEnds( false );
599   MeasurementVectorType measurementVectorAbove( numberOfComponents );
600   for( unsigned int gupk1 = 0; gupk1<numberOfComponents; gupk1++)
601     {
602     measurementVectorAbove[gupk1] = 129.9;
603     }
604 
605   IndexType aboveUpperIndex( numberOfComponents );
606   bool aboveUpperIndexBool =
607     histogram->GetIndex( measurementVectorAbove, aboveUpperIndex );
608   if( !aboveUpperIndexBool )
609     {
610     std::cerr << "Upper bound index = " << aboveUpperIndex << std::endl;
611     }
612 
613   // Get the mean value for a dimension
614   unsigned int dimension = 0;
615   double mean = histogram->Mean( dimension );
616   std::cout << "Mean value along dimension " << dimension << " : " << mean << std::endl;
617 
618   HistogramType::Iterator itr = histogram->Begin();
619   HistogramType::Iterator end = histogram->End();
620 
621   HistogramType::TotalAbsoluteFrequencyType totalFrequency =
622     histogram->GetTotalFrequency();
623 
624   InstanceIdentifier histogramSize = histogram->Size();
625 
626   while( itr != end )
627     {
628     itr.SetFrequency( itr.GetFrequency() + 1 );
629     ++itr;
630     }
631 
632   HistogramType::TotalAbsoluteFrequencyType newTotalFrequency =
633     histogram->GetTotalFrequency();
634 
635   if( newTotalFrequency != histogramSize + totalFrequency )
636     {
637     std::cerr << "Get/SetFrequency error in the Iterator" << std::endl;
638     return EXIT_FAILURE;
639     }
640 
641 
642   //
643   // Exercise GetIndex() method in the iterator.
644   //
645   std::cout << "TEST GetIndex() and GetFrequency() in the iterator" << std::endl;
646   itr = histogram->Begin();
647   end = histogram->End();
648 
649   // Print out only some of them, the first 10...
650   for( unsigned int kk = 0; kk < 10 && itr != end; ++itr, ++kk )
651     {
652     std::cout << itr.GetIndex() <<  " : " << itr.GetFrequency() << std::endl;
653     }
654 
655 
656   //
657   // Exercise GetMin / GetMax methods
658   //
659     {
660     const double epsilon = 1e-6;
661     HistogramType::SizeType size2 = histogram->GetSize();
662 
663     HistogramType::BinMinContainerType binMinimums = histogram->GetMins();
664 
665     for( unsigned int dim = 0; dim < numberOfComponents; dim++ )
666       {
667       HistogramType::BinMinVectorType binDimensionMinimums = histogram->GetDimensionMins( dim );
668       for( unsigned int k = 0; k < size2[dim]; k++ )
669         {
670         HistogramType::MeasurementType minA = binMinimums[dim][k];
671         HistogramType::MeasurementType minB = binDimensionMinimums[k];
672         HistogramType::MeasurementType minC = histogram->GetBinMin( dim, k );
673         if( ( itk::Math::abs( minA - minB ) > epsilon ) ||
674             ( itk::Math::abs( minA - minC ) > epsilon )    )
675           {
676           std::cerr << "Error in Get Bin Mins methods" << std::endl;
677           std::cerr << "dim = " << dim << " k = " << k << std::endl;
678           std::cerr << "GetMins()          = " << minA << std::endl;
679           std::cerr << "GetDimensionMins() = " << minB << std::endl;
680           std::cerr << "GetMin()           = " << minC << std::endl;
681           return EXIT_FAILURE;
682           }
683         }
684       }
685 
686     HistogramType::BinMaxContainerType binMaximums = histogram->GetMaxs();
687 
688     for( unsigned int dim = 0; dim < numberOfComponents; dim++ )
689       {
690       HistogramType::BinMaxVectorType binDimensionMaximums = histogram->GetDimensionMaxs( dim );
691       for( unsigned int k = 0; k < size2[dim]; k++ )
692         {
693         HistogramType::MeasurementType maxA = binMaximums[dim][k];
694         HistogramType::MeasurementType maxB = binDimensionMaximums[k];
695         HistogramType::MeasurementType maxC = histogram->GetBinMax( dim, k );
696         if( ( itk::Math::abs( maxA - maxB ) > epsilon ) ||
697             ( itk::Math::abs( maxA - maxC ) > epsilon )    )
698           {
699           std::cerr << "Error in Get Bin Maxs methods" << std::endl;
700           std::cerr << "dim = " << dim << " k = " << k << std::endl;
701           std::cerr << "GetMaxs()          = " << maxA << std::endl;
702           std::cerr << "GetDimensionMaxs() = " << maxB << std::endl;
703           std::cerr << "GetMax()           = " << maxC << std::endl;
704           return EXIT_FAILURE;
705           }
706         }
707       }
708     }
709 
710 
711   // Testing methods specific to Iterators
712     {
713     using IteratorType = HistogramType::Iterator;
714     IteratorType iter = histogram->Begin();
715     IteratorType iter2 = histogram->End();
716 
717     iter2 = iter;
718     if( iter2 != iter )
719       {
720       std::cerr << "Iterator operator=() failed" << std::endl;
721       return EXIT_FAILURE;
722       }
723 
724     IteratorType iter3( histogram );
725     if( iter3 != histogram->Begin() )
726       {
727       std::cerr << "Iterator constructor from histogram failed" << std::endl;
728       return EXIT_FAILURE;
729       }
730 
731     unsigned int counter = 0;
732     while( iter3 != histogram->End() )
733       {
734       ++iter3;
735       counter++;
736       }
737 
738     if( counter != histogram->Size() )
739       {
740       std::cerr << "Iterator walk failed" << std::endl;
741       return EXIT_FAILURE;
742       }
743 
744     IteratorType iter4( iter2 );
745     if( iter4 != iter2 )
746       {
747       std::cerr << "Iterator copy constructor failed" << std::endl;
748       return EXIT_FAILURE;
749       }
750 
751     IteratorType iter5 = iter2;
752     if( iter5 != iter2 )
753       {
754       std::cerr << "Iterator operator= failed" << std::endl;
755       return EXIT_FAILURE;
756       }
757 
758     IteratorType iter6( 7, histogram );
759     if( iter6.GetInstanceIdentifier() != 7 )
760       {
761       std::cerr << "Iterator Constructor with instance identifier 7 failed" << std::endl;
762       return EXIT_FAILURE;
763       }
764 
765     }
766 
767   // Testing methods specific to ConstIterators
768     {
769     using ConstIteratorType = HistogramType::ConstIterator;
770     ConstIteratorType iter = histogram->Begin();
771     ConstIteratorType iter2 = histogram->End();
772 
773     iter2 = iter;
774 
775     if( iter2 != iter )
776       {
777       std::cerr << "ConstIterator operator!=() or operator=() failed" << std::endl;
778       return EXIT_FAILURE;
779       }
780 
781     if( !( iter2 == iter ) )
782       {
783       std::cerr << "ConstIterator operator==() failed" << std::endl;
784       return EXIT_FAILURE;
785       }
786 
787     ConstIteratorType iter3( iter2 );
788     if( iter3 != iter2 )
789       {
790       std::cerr << "ConstIterator copy constructor failed" << std::endl;
791       return EXIT_FAILURE;
792       }
793 
794     const HistogramType * constHistogram = histogram.GetPointer();
795 
796     ConstIteratorType iter4( constHistogram->Begin() );
797     ConstIteratorType iter5( histogram->Begin() );
798     if( iter4 != iter5 )
799       {
800       std::cerr << "Constructor from const container Begin() differs from non-const Begin() " << std::endl;
801       return EXIT_FAILURE;
802       }
803 
804     ConstIteratorType iter6( constHistogram );
805     ConstIteratorType iter7( histogram );
806     if( iter6 != iter7 )
807       {
808       std::cerr << "ConstIterator Constructor from const container differs from non-const container" << std::endl;
809       return EXIT_FAILURE;
810       }
811 
812     ConstIteratorType iter8( histogram );
813     if( iter8.GetInstanceIdentifier() != 0 )
814       {
815       std::cerr << "Constructor with instance identifier 0 failed" << std::endl;
816       return EXIT_FAILURE;
817       }
818 
819     unsigned int counter = 0;
820     ConstIteratorType iter10( constHistogram );
821     if( iter10 != constHistogram->Begin() )
822       {
823       std::cerr << "ConstIterator constructor from histogram failed" << std::endl;
824       return EXIT_FAILURE;
825       }
826 
827 
828     while( iter10 != constHistogram->End() )
829       {
830       ++iter10;
831       counter++;
832       }
833 
834     if( counter != constHistogram->Size() )
835       {
836       std::cerr << "Iterator walk failed" << std::endl;
837       return EXIT_FAILURE;
838       }
839 
840     }
841 
842   if( !pass )
843     {
844     std::cout << "Test failed in " << whereFail << "." << std::endl;
845     return EXIT_FAILURE;
846     }
847 
848   std::cout << "Test passed." << std::endl;
849   return EXIT_SUCCESS;
850 
851 }
852