/*========================================================================= * * 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 * * 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. * *=========================================================================*/ // Software Guide : BeginLatex // // This example shows how to create an \subdoxygen{Statistics}{Histogram} // object and use it. // // \index{itk::Sample!Histogram} // // We call an instance in a \code{Histogram} object a \emph{bin}. The // Histogram differs from the // \subdoxygen{Statistics}{ListSample}, // \subdoxygen{Statistics}{ImageToListSampleAdaptor}, or // \subdoxygen{Statistics}{PointSetToListSampleAdaptor} in significant ways. // Histograms can have a variable number of values (\code{float} // type) for each measurement vector, while the three other classes // have a fixed value (one) for all measurement vectors. Also // those array-type containers can have multiple instances (data // elements) with identical measurement vector values. However, // in a Histogram object, there is one unique instance for any // given measurement vector. // // \begin{figure} // \centering // \includegraphics[width=0.4\textwidth]{Histogram} // \itkcaption[Histogram]{Conceptual histogram data structure.} // \protect\label{fig:StatHistogram} // \end{figure} // Software Guide : EndLatex // Software Guide : BeginCodeSnippet #include "itkHistogram.h" #include "itkDenseFrequencyContainer2.h" // Software Guide : EndCodeSnippet int main() { // Software Guide : BeginLatex // // Here we create a histogram with dense frequency containers. In // this example we will not have any zero-frequency measurements, // so the dense frequency container is the appropriate choice. If // the histogram is expected to have many empty (zero) bins, a sparse // frequency container would be the better option. Here we also set // the size of the measurement vectors to be 2 components. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet using MeasurementType = float; using FrequencyContainerType = itk::Statistics::DenseFrequencyContainer2; using FrequencyType = FrequencyContainerType::AbsoluteFrequencyType; constexpr unsigned int numberOfComponents = 2; using HistogramType = itk::Statistics::Histogram; HistogramType::Pointer histogram = HistogramType::New(); histogram->SetMeasurementVectorSize(numberOfComponents); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // We initialize it as a $3\times3$ histogram with equal size intervals. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet HistogramType::SizeType size(numberOfComponents); size.Fill(3); HistogramType::MeasurementVectorType lowerBound(numberOfComponents); HistogramType::MeasurementVectorType upperBound(numberOfComponents); lowerBound[0] = 1.1; lowerBound[1] = 2.6; upperBound[0] = 7.1; upperBound[1] = 8.6; histogram->Initialize(size, lowerBound, upperBound); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Now the histogram is ready for storing frequency values. We will // fill each bin's frequency according to the Figure // \ref{fig:StatHistogram}. There are three ways of accessing data // elements in the histogram: // \begin{itemize} // \item using instance identifiers---just like any other Sample object; // \item using n-dimensional indices---just like an Image object; // \item using an iterator---just like any other Sample object. // \end{itemize} // In this example, the index $(0, 0)$ refers the same bin as the instance // identifier (0) refers to. The instance identifier of the index (0, // 1) is (3), (0, 2) is (6), (2, 2) is (8), and so on. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet histogram->SetFrequency(0UL, static_cast(0.0)); histogram->SetFrequency(1UL, static_cast(2.0)); histogram->SetFrequency(2UL, static_cast(3.0)); histogram->SetFrequency(3UL, static_cast(2.0f)); histogram->SetFrequency(4UL, static_cast(0.5f)); histogram->SetFrequency(5UL, static_cast(1.0f)); histogram->SetFrequency(6UL, static_cast(5.0f)); histogram->SetFrequency(7UL, static_cast(2.5f)); histogram->SetFrequency(8UL, static_cast(0.0f)); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Let us examine if the frequency is set correctly by calling the // \code{GetFrequency(index)} method. We can use the // \code{GetFrequency(instance identifier)} method for the same purpose. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet HistogramType::IndexType index(numberOfComponents); index[0] = 0; index[1] = 2; std::cout << "Frequency of the bin at index " << index << " is " << histogram->GetFrequency(index) << ", and the bin's instance identifier is " << histogram->GetInstanceIdentifier(index) << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // For test purposes, we create a measurement vector and an index // that belongs to the center bin. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet HistogramType::MeasurementVectorType mv(numberOfComponents); mv[0] = 4.1; mv[1] = 5.6; index.Fill(1); // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // We retrieve the measurement vector at the index value (1, 1), the center // bin's measurement vector. The output is [4.1, 5.6]. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet std::cout << "Measurement vector at the center bin is " << histogram->GetMeasurementVector(index) << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // Since all the measurement vectors are unique in the Histogram class, we // can determine the index from a measurement vector. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet HistogramType::IndexType resultingIndex; histogram->GetIndex(mv, resultingIndex); std::cout << "Index of the measurement vector " << mv << " is " << resultingIndex << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // In a similar way, we can get the instance identifier from the index. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet std::cout << "Instance identifier of index " << index << " is " << histogram->GetInstanceIdentifier(index) << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // If we want to check if an index is valid, we use the method // \code{IsIndexOutOfBounds(index)}. The following code snippet fills the // index variable with (100, 100). It is obviously not a valid index. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet index.Fill(100); if (histogram->IsIndexOutOfBounds(index)) { std::cout << "Index " << index << " is out of bounds." << std::endl; } // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The following code snippets show how to get the histogram size // and frequency dimension. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet std::cout << "Number of bins = " << histogram->Size() << " Total frequency = " << histogram->GetTotalFrequency() << " Dimension sizes = " << histogram->GetSize() << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The Histogram class has a quantile calculation method, // \code{Quantile(dimension, percent)}. The following code returns the 50th // percentile along the first dimension. Note that the quantile calculation // considers only one dimension. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet std::cout << "50th percentile along the first dimension = " << histogram->Quantile(0, 0.5) << std::endl; // Software Guide : EndCodeSnippet return EXIT_SUCCESS; }