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 // Software Guide : BeginLatex
20 //
21 // \index{itk::Statistics::Subsample}
22 //
23 // The \subdoxygen{Statistics}{Subsample} is a derived sample. In other
24 // words, it requires another \subdoxygen{Statistics}{Sample} object for
25 // storing measurement vectors. The Subsample class stores a subset of
26 // instance identifiers from another Sample object.  \emph{Any} Sample's
27 // subclass can be the source Sample object. You can create a Subsample
28 // object out of another Subsample object. The Subsample class is useful for
29 // storing classification results from a test Sample object or for just
30 // extracting some part of interest in a Sample object. Another good use of
31 // Subsample is sorting a Sample object. When we use an \doxygen{Image}
32 // object as the data source, we do not want to change the order of data
33 // elements in the image. However, we sometimes want to sort or
34 // select data elements according to their order. Statistics algorithms for
35 // this purpose accepts only Subsample objects as inputs. Changing the order
36 // in a Subsample object does not change the order of the source sample.
37 //
38 // To use a Subsample object, we include the header files for
39 // the class itself and a Sample class. We will use the
40 // \subdoxygen{Statistics}{ListSample} as the input sample.
41 //
42 // Software Guide : EndLatex
43 
44 
45 // Software Guide : BeginCodeSnippet
46 #include "itkListSample.h"
47 #include "itkSubsample.h"
48 // Software Guide : EndCodeSnippet
49 
50 // Software Guide : BeginLatex
51 //
52 // We need another header for measurement vectors. We are going to use
53 // the \doxygen{Vector} class in this example.
54 //
55 // Software Guide : EndLatex
56 
57 // Software Guide : BeginCodeSnippet
58 #include "itkVector.h"
59 // Software Guide : EndCodeSnippet
60 
main()61 int main()
62 {
63   // Software Guide : BeginLatex
64   //
65   // The following code snippet will create a ListSample object
66   // with three-component float measurement vectors and put three
67   // measurement vectors into the list.
68   //
69   // Software Guide : EndLatex
70 
71   // Software Guide : BeginCodeSnippet
72   using MeasurementVectorType = itk::Vector< float, 3 >;
73   using SampleType = itk::Statistics::ListSample< MeasurementVectorType >;
74   SampleType::Pointer sample = SampleType::New();
75   MeasurementVectorType mv;
76   mv[0] = 1.0;
77   mv[1] = 2.0;
78   mv[2] = 4.0;
79 
80   sample->PushBack(mv);
81 
82   mv[0] = 2.0;
83   mv[1] = 4.0;
84   mv[2] = 5.0;
85   sample->PushBack(mv);
86 
87   mv[0] = 3.0;
88   mv[1] = 8.0;
89   mv[2] = 6.0;
90   sample->PushBack(mv);
91   // Software Guide : EndCodeSnippet
92 
93   // Software Guide : BeginLatex
94   //
95   // To create a Subsample instance, we define the type of the Subsample with
96   // the source sample type, in this case, the previously defined
97   // \code{SampleType}. As usual, after that, we call the \code{New()} method
98   // to create an instance. We must plug in the source sample, \code{sample},
99   // using the \code{SetSample()} method. However, with regard to data
100   // elements, the Subsample is empty. We specify which data elements, among
101   // the data elements in the Sample object, are part of the
102   // Subsample. There are two ways of doing that. First, if we want to
103   // include every data element (instance) from the sample, we simply call
104   // the \code{InitializeWithAllInstances()} method like the following:
105   //
106   // \small
107   // \begin{verbatim}
108   //   subsample->InitializeWithAllInstances();
109   // \end{verbatim}
110   // \normalsize
111   //
112   // This method is useful when we want to create a Subsample
113   // object for sorting all the data elements in a Sample
114   // object. However, in most cases, we want to include only a subset of
115   // a Sample object. For this purpose, we use the
116   // \code{AddInstance(instance identifier)} method in this example. In
117   // the following code snippet, we include only the first and last
118   // instance in our subsample object from the three instances
119   // of the Sample class.
120   //
121   // Software Guide : EndLatex
122 
123   // Software Guide : BeginCodeSnippet
124   using SubsampleType = itk::Statistics::Subsample< SampleType >;
125   SubsampleType::Pointer subsample = SubsampleType::New();
126   subsample->SetSample( sample );
127 
128   subsample->AddInstance( 0UL );
129   subsample->AddInstance( 2UL );
130   // Software Guide : EndCodeSnippet
131 
132   // Software Guide : BeginLatex
133   //
134   // The Subsample is ready for use. The following code snippet
135   // shows how to use \code{Iterator} interfaces.
136   //
137   // Software Guide : EndLatex
138 
139   // Software Guide : BeginCodeSnippet
140   SubsampleType::Iterator iter = subsample->Begin();
141   while ( iter != subsample->End() )
142     {
143     std::cout << "instance identifier = " << iter.GetInstanceIdentifier()
144               << "\t measurement vector = "
145               << iter.GetMeasurementVector()
146               << "\t frequency = "
147               << iter.GetFrequency()
148               << std::endl;
149     ++iter;
150     }
151   // Software Guide : EndCodeSnippet
152 
153 
154   // Software Guide : BeginLatex
155   //
156   // As mentioned earlier, the instances in a Subsample can be sorted without
157   // changing the order in the source Sample. For this purpose, the Subsample
158   // provides an additional instance indexing scheme. The indexing scheme is
159   // just like the instance identifiers for the Sample. The index is an
160   // integer value starting at 0, and the last value is one less than the
161   // number of all instances in a Subsample. The \code{Swap(0, 1)} method,
162   // for example, swaps two instance identifiers of the first data element
163   // and the second element in the Subsample. Internally, the \code{Swap()}
164   // method changes the instance identifiers in the first and second
165   // position. Using indices, we can print out the effects of the
166   // \code{Swap()} method. We use the
167   // \code{GetMeasurementVectorByIndex(index)} to get the measurement vector
168   // at the index position. However, if we want to use the common methods of
169   // Sample that accepts instance identifiers, we call them after we get
170   // the instance identifiers using \code{GetInstanceIdentifier(index)}
171   // method.
172   //
173   // Software Guide : EndLatex
174 
175   // Software Guide : BeginCodeSnippet
176   subsample->Swap(0, 1);
177 
178   for ( int index = 0; index < subsample->Size(); ++index )
179     {
180     std::cout << "instance identifier = "
181               << subsample->GetInstanceIdentifier(index)
182               << "\t measurement vector = "
183               << subsample->GetMeasurementVectorByIndex(index)
184               << std::endl;
185     }
186   // Software Guide : EndCodeSnippet
187 
188   // Software Guide : BeginLatex
189   //
190   // Since we are using a ListSample object as the source sample, the
191   // following code snippet will return the same value (2) for the
192   // \code{Size()} and the \code{GetTotalFrequency()} methods. However, if we
193   // used a Histogram object as the source sample, the two return
194   // values might be different because a Histogram allows varying
195   // frequency values for each instance.
196   //
197   // Software Guide : EndLatex
198 
199   // Software Guide : BeginCodeSnippet
200   std::cout << "Size = " << subsample->Size() << std::endl;
201   std::cout << "Total frequency = "
202             << subsample->GetTotalFrequency() << std::endl;
203   // Software Guide : EndCodeSnippet
204 
205   // Software Guide : BeginLatex
206   //
207   // If we want to remove all instances that are associated with the
208   // Subsample, we call the \code{Clear()} method. After this invocation, the
209   // \code{Size()} and the \code{GetTotalFrequency()} methods return 0.
210   //
211   // Software Guide : EndLatex
212 
213   // Software Guide : BeginCodeSnippet
214   subsample->Clear();
215   std::cout << "Size = " << subsample->Size() << std::endl;
216   std::cout << "Total frequency = "
217             << subsample->GetTotalFrequency() << std::endl;
218   // Software Guide : EndCodeSnippet
219 
220   return EXIT_SUCCESS;
221 }
222