/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  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
 *
 *         https://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.
 *
 *=========================================================================*/

// Software Guide : BeginLatex
//
// \index{Statistics!Importing ListSample to Histogram}
// \index{itk::Statistics::List\-Sample\-To\-Histogram\-Filter}
//
// Sometimes we want to work with a histogram instead of a list of
// measurement vectors (e.g. \subdoxygen{Statistics}{ListSample},
// \subdoxygen{Statistics}{ImageToListSampleAdaptor}, or
// \subdoxygen{Statistics}{PointSetToListSample}) to use less memory or to
// perform a particular type of analysis. In such cases, we can import data
// from a sample type to a \subdoxygen{Statistics}{Histogram} object
// using the \subdoxygen{Statistics}{SampleToHistogramFiler}.
//
// We use a ListSample object as the input for the filter. We include the
// header files for the ListSample and Histogram classes, as well as the
// filter.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkListSample.h"
#include "itkHistogram.h"
#include "itkSampleToHistogramFilter.h"
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
//
// We need another header for the type of the measurement vectors. We are
// going to use the \doxygen{Vector} class which is a subclass of the
// \doxygen{FixedArray} in this example.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkVector.h"
// Software Guide : EndCodeSnippet

int
main()
{
  // Software Guide : BeginLatex
  //
  // The following code snippet creates a ListSample object with
  // two-component \code{int} measurement vectors and put the measurement
  // vectors: [1,1] - 1 time, [2,2] - 2 times, [3,3] - 3 times, [4,4] - 4
  // times, [5,5] - 5 times into the \code{listSample}.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using MeasurementType = int;
  constexpr unsigned int MeasurementVectorLength = 2;
  using MeasurementVectorType =
    itk::Vector<MeasurementType, MeasurementVectorLength>;

  using ListSampleType = itk::Statistics::ListSample<MeasurementVectorType>;
  auto listSample = ListSampleType::New();
  listSample->SetMeasurementVectorSize(MeasurementVectorLength);

  MeasurementVectorType mv;
  for (unsigned int i = 1; i < 6; ++i)
  {
    for (unsigned int j = 0; j < 2; ++j)
    {
      mv[j] = (MeasurementType)i;
    }
    for (unsigned int j = 0; j < i; ++j)
    {
      listSample->PushBack(mv);
    }
  }
  // Software Guide : EndCodeSnippet


  // Software Guide : BeginLatex
  //
  // Here, we set up the size and bound of the output histogram.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using HistogramMeasurementType = float;
  constexpr unsigned int numberOfComponents = 2;
  using HistogramType = itk::Statistics::Histogram<HistogramMeasurementType>;

  HistogramType::SizeType size(numberOfComponents);
  size.Fill(5);

  HistogramType::MeasurementVectorType lowerBound(numberOfComponents);
  HistogramType::MeasurementVectorType upperBound(numberOfComponents);

  lowerBound[0] = 0.5;
  lowerBound[1] = 0.5;

  upperBound[0] = 5.5;
  upperBound[1] = 5.5;
  // Software Guide : EndCodeSnippet


  // Software Guide : BeginLatex
  //
  // Now, we set up the \code{SampleToHistogramFilter} object by passing
  // \code{listSample} as the input and initializing the histogram size
  // and bounds with the \code{SetHistogramSize()},
  // \code{SetHistogramBinMinimum()}, and \code{SetHistogramBinMaximum()}
  // methods. We execute the filter by calling the \code{Update()}
  // method.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  using FilterType =
    itk::Statistics::SampleToHistogramFilter<ListSampleType, HistogramType>;
  auto filter = FilterType::New();

  filter->SetInput(listSample);
  filter->SetHistogramSize(size);
  filter->SetHistogramBinMinimum(lowerBound);
  filter->SetHistogramBinMaximum(upperBound);
  filter->Update();
  // Software Guide : EndCodeSnippet

  // Software Guide : BeginLatex
  //
  // The \code{Size()} and \code{GetTotalFrequency()} methods return the same
  // values as the \code{sample} does.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  const HistogramType * histogram = filter->GetOutput();

  HistogramType::ConstIterator iter = histogram->Begin();
  while (iter != histogram->End())
  {
    std::cout << "Measurement vectors = " << iter.GetMeasurementVector()
              << " frequency = " << iter.GetFrequency() << std::endl;
    ++iter;
  }

  std::cout << "Size = " << histogram->Size() << std::endl;
  std::cout << "Total frequency = " << histogram->GetTotalFrequency()
            << std::endl;
  // Software Guide : EndCodeSnippet

  return EXIT_SUCCESS;
}
