text: /*=========================================================================
   *
   *  Copyright Insight Software Consortium
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *         http://www.apache.org/licenses/LICENSE-2.0.txt
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   *=========================================================================*/
  
  #include "itkListSample.h"
  #include "itkHistogram.h"
  #include "itkSampleToHistogramFilter.h"
  
  int itkSampleToHistogramFilterTest7( int, char * [] )
  {
  
    constexpr unsigned int numberOfComponents = 3;
    using MeasurementType = signed int;    // Exercise an integer type for the samples
  
    using MeasurementVectorType = itk::VariableLengthVector< float >;
  
    using SampleType = itk::Statistics::ListSample< MeasurementVectorType >;
  
    using HistogramType = itk::Statistics::Histogram< MeasurementType,
            itk::Statistics::DenseFrequencyContainer2 >;
  
    using FilterType = itk::Statistics::SampleToHistogramFilter<
      SampleType, HistogramType >;
  
    using HistogramSizeType = FilterType::HistogramSizeType;
    using HistogramMeasurementVectorType = FilterType::HistogramMeasurementVectorType;
  
    FilterType::Pointer filter = FilterType::New();
    SampleType::Pointer sample = SampleType::New();
  
  
    HistogramMeasurementVectorType minimum( numberOfComponents );
    HistogramMeasurementVectorType maximum( numberOfComponents );
  
    minimum[0] = -17;
    minimum[1] = -19;
    minimum[2] = -24;
  
    maximum[0] =  17;
    maximum[1] =  19;
    maximum[2] =  24;
  
    HistogramSizeType histogramSize( numberOfComponents );
  
    histogramSize[0] = 36;
    histogramSize[1] = 40;
    histogramSize[2] = 50;
  
    MeasurementVectorType measure( numberOfComponents );
  
    sample->SetMeasurementVectorSize( numberOfComponents );
  
    // Populate the Sample
    for( unsigned int i=0; i < histogramSize[0]; i++ )
      {
      measure[0] = minimum[0] + static_cast<double>(i);
      for( unsigned int j=0; j < histogramSize[1]; j++ )
        {
        measure[1] = minimum[1] + static_cast<double>(j);
        for( unsigned int k=0; k < histogramSize[2]; k++ )
          {
          measure[2] = minimum[2] + static_cast<double>(k);
          sample->PushBack( measure );
          }
        }
      }
  
    filter->SetInput( sample );
  
    // Test exception when calling Update() without having
    // defined the size of the histogram in the filter.
    try
      {
      filter->Update();
      std::cerr << "Failure to throw expected exception due to lack";
      std::cerr << " of calling SetHistogramSize() in the filter ";
      return EXIT_FAILURE;
      }
    catch( itk::ExceptionObject & )
      {
      std::cout << "Expected exception received" << std::endl;
      }
  
  
    const HistogramType * histogram = filter->GetOutput();
  
    if( histogram->Size() != 0 )
      {
      std::cerr << "Histogram Size should have been zero" << std::endl;
      return EXIT_FAILURE;
      }
  
  
    filter->SetHistogramSize( histogramSize );
  
    try
      {
      filter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
  
    const unsigned int expectedHistogramSize1 =
      histogramSize[0] * histogramSize[1] * histogramSize[2];
  
    if( histogram->Size() != expectedHistogramSize1 )
      {
      std::cerr << "Histogram Size error" << std::endl;
      std::cerr << "We expected " << expectedHistogramSize1 << std::endl;
      std::cerr << "We received " << histogram->Size() << std::endl;
      return EXIT_FAILURE;
      }
  
  
    HistogramType::ConstIterator histogramItr = histogram->Begin();
    HistogramType::ConstIterator histogramEnd = histogram->End();
  
    constexpr unsigned int expectedFrequency1 = 1;
    while( histogramItr != histogramEnd )
      {
      if( histogramItr.GetFrequency() != expectedFrequency1 )
        {
        std::cerr << "Histogram bin error for measure " << std::endl;
        std::cerr << histogramItr.GetMeasurementVector() << std::endl;
        std::cerr << "Expected frequency = " << expectedFrequency1 << std::endl;
        std::cerr << "Computed frequency = " << histogramItr.GetFrequency() << std::endl;
        }
      ++histogramItr;
      }
  
    // Exercise the saturation of the maximum
    maximum[0] =  itk::NumericTraits< MeasurementType >::max();
    maximum[1] =  itk::NumericTraits< MeasurementType >::max();
    maximum[2] =  itk::NumericTraits< MeasurementType >::max();
  
    minimum[0] =  itk::NumericTraits< MeasurementType >::min();
    minimum[1] =  itk::NumericTraits< MeasurementType >::min();
    minimum[2] =  itk::NumericTraits< MeasurementType >::min();
  
    filter->SetHistogramBinMaximum( maximum );
    filter->SetHistogramBinMinimum( minimum );
    filter->SetAutoMinimumMaximum( true );
  
    try
      {
      filter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
  
  
    filter->SetAutoMinimumMaximum( false );
  
    // Add a sample that will exercise the overflow code
    //
    measure[0] = itk::NumericTraits< MeasurementType >::max();
    measure[1] = itk::NumericTraits< MeasurementType >::max();
    measure[2] = itk::NumericTraits< MeasurementType >::max();
  
    sample->PushBack( measure );
    sample->Modified();
  
    try
      {
      filter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
  
  
    filter->SetAutoMinimumMaximum( true );
  
  
    try
      {
      filter->Update();
      }
    catch( itk::ExceptionObject & excp )
      {
      std::cerr << excp << std::endl;
      return EXIT_FAILURE;
      }
  
  
    std::cout << "Test passed." << std::endl;
    return EXIT_SUCCESS;
  }
  