/*========================================================================= * * 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. * *=========================================================================*/ #ifndef itkSubsample_h #define itkSubsample_h #include "itkSample.h" #include "itkMacro.h" #include "itkObjectFactory.h" namespace itk { namespace Statistics { /** * \class Subsample * \brief This class stores a subset of instance identifiers from another sample * object. You can create a subsample out of another sample object or another * subsample object. The class is useful when storing or extracting a portion * of a sample object. Note that when the elements of a subsample are sorted, * the instance identifiers of the subsample are sorted without changing the * original source sample. Most Statistics algorithms (that derive from * StatisticsAlgorithmBase accept Subsample objects as inputs). * * \ingroup ITKStatistics */ template class ITK_TEMPLATE_EXPORT Subsample : public TSample { public: ITK_DISALLOW_COPY_AND_MOVE(Subsample); /** Standard class type aliases */ using Self = Subsample; using Superclass = TSample; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(Subsample); /** standard New() method support */ itkNewMacro(Self); /** Smart pointer to the actual sample data holder */ using SamplePointer = typename TSample::Pointer; /** Typedefs for Measurement vector, measurement, Instance Identifier, * frequency, size, size element value from the template argument TSample */ using MeasurementVectorType = typename TSample::MeasurementVectorType; using MeasurementType = typename TSample::MeasurementType; using InstanceIdentifier = typename TSample::InstanceIdentifier; using ValueType = MeasurementVectorType; using AbsoluteFrequencyType = typename TSample::AbsoluteFrequencyType; using TotalAbsoluteFrequencyType = typename TSample::TotalAbsoluteFrequencyType; /** Type of the storage for instances that belong to the class * represented by a Subsample object. A Subsample object stores * only the InstanceIdentifiers. The actual data is still in the Sample * object */ using InstanceIdentifierHolder = std::vector; // Disable clang warning false positive. // #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Winconsistent-missing-override") # pragma clang diagnostic push # pragma clang diagnostic ignored "-Winconsistent-missing-override" # endif #endif /** Get the Id Holder */ const InstanceIdentifierHolder & GetIdHolder() const { return this->m_IdHolder; } #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Winconsistent-missing-override") # pragma clang diagnostic pop # endif #endif /** Plug in the actual sample data */ void SetSample(const TSample * sample); const TSample * GetSample() const; /** Initialize the subsample with all instances of the sample */ void InitializeWithAllInstances(); /** Add instance to the subsample */ void AddInstance(InstanceIdentifier id); /** returns SizeType object whose each element is the number of * elements in each dimension */ InstanceIdentifier Size() const override; /** Clear the subsample */ void Clear(); /** returns the measurement of the instance which is identified * by the 'id' */ const MeasurementVectorType & GetMeasurementVector(InstanceIdentifier id) const override; /** returns the frequency of the instance which is identified by the 'id' */ AbsoluteFrequencyType GetFrequency(InstanceIdentifier id) const override; /** returns the total frequency for the 'd' dimension */ TotalAbsoluteFrequencyType GetTotalFrequency() const override; void Swap(unsigned int index1, unsigned int index2); InstanceIdentifier GetInstanceIdentifier(unsigned int index); const MeasurementVectorType & GetMeasurementVectorByIndex(unsigned int index) const; AbsoluteFrequencyType GetFrequencyByIndex(unsigned int index) const; /** Method to graft another sample */ void Graft(const DataObject * thatObject) override; class ConstIterator { friend class Subsample; public: ConstIterator(const Self * sample) { *this = sample->Begin(); } ConstIterator(const ConstIterator & iter) { m_Iter = iter.m_Iter; m_Subsample = iter.m_Subsample; m_Sample = iter.m_Sample; } ConstIterator & operator=(const ConstIterator & iter) { m_Iter = iter.m_Iter; m_Subsample = iter.m_Subsample; m_Sample = iter.m_Sample; return *this; } bool operator==(const ConstIterator & it) const { return (m_Iter == it.m_Iter); } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstIterator); ConstIterator & operator++() { ++m_Iter; return *this; } AbsoluteFrequencyType GetFrequency() const { return m_Sample->GetFrequency(*m_Iter); } const MeasurementVectorType & GetMeasurementVector() const { return m_Sample->GetMeasurementVector(*m_Iter); } InstanceIdentifier GetInstanceIdentifier() const { return (m_Iter - m_Subsample->GetIdHolder().begin()); } protected: // Purposely not implemented ConstIterator(); // Only to be called from the Subsample ConstIterator(typename InstanceIdentifierHolder::const_iterator iter, const Self * classSample) : m_Iter(iter) , m_Subsample(classSample) , m_Sample(classSample->GetSample()) {} // ConstIterator pointing to ImageToListSampleAdaptor typename InstanceIdentifierHolder::const_iterator m_Iter; // Pointer to Subsample object const Self * m_Subsample; const TSample * m_Sample; private: }; class Iterator : public ConstIterator { friend class Subsample; public: Iterator(Self * sample) : ConstIterator(sample) {} Iterator(const Iterator & iter) : ConstIterator(iter) {} Iterator & operator=(const Iterator & iter) { this->ConstIterator::operator=(iter); return *this; } protected: // To ensure const-correctness these method must not be in the public API. // The are purposely not implemented, since they should never be called. Iterator(); Iterator(const Self * sample); Iterator(typename InstanceIdentifierHolder::const_iterator iter, const Self * classSample); Iterator(const ConstIterator & it); ConstIterator & operator=(const ConstIterator & it); // Only to be called from the Subsample Iterator(typename InstanceIdentifierHolder::iterator iter, Self * classSample) : ConstIterator(iter, classSample) {} private: }; /** This method returns an iterator to the beginning of the measurement vectors */ Iterator Begin() { Iterator iter(m_IdHolder.begin(), this); return iter; } /** This method returns an iterator to the beginning of the measurement vectors */ Iterator End() { Iterator iter(m_IdHolder.end(), this); return iter; } ConstIterator Begin() const { ConstIterator iter(m_IdHolder.begin(), this); return iter; } ConstIterator End() const { ConstIterator iter(m_IdHolder.end(), this); return iter; } protected: Subsample(); ~Subsample() override = default; void PrintSelf(std::ostream & os, Indent indent) const override; private: const TSample * m_Sample{}; InstanceIdentifierHolder m_IdHolder{}; unsigned int m_ActiveDimension{}; TotalAbsoluteFrequencyType m_TotalFrequency{}; }; // end of class } // end of namespace Statistics } // end of namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkSubsample.hxx" #endif #endif