1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
|
/*=========================================================================
*
* 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.
*
*=========================================================================*/
#ifndef sitkProcessObject_h
#define sitkProcessObject_h
#include "sitkCommon.h"
#include "sitkNonCopyable.h"
#include "sitkTemplateFunctions.h"
#include "sitkEvent.h"
#include "sitkImage.h"
#include <iostream>
#include <list>
namespace itk {
#ifndef SWIG
template< typename T, unsigned int NVectorDimension > class Vector;
class ProcessObject;
class Command;
class EventObject;
#endif
namespace simple {
class Command;
/** \class ProcessObject
* \brief Base class for SimpleITK classes based on ProcessObject
*
*/
class SITKCommon_EXPORT ProcessObject:
protected NonCopyable
{
public:
typedef ProcessObject Self;
/**
* Default Constructor that takes no arguments and initializes
* default parameters
*/
ProcessObject();
/**
* Default Destructor
*/
virtual ~ProcessObject();
// Print ourselves out
virtual std::string ToString() const;
/** return user readable name for the filter */
virtual std::string GetName() const = 0;
/** Turn debugging output on/off.
*
* Enabling debugging prints additional information to stdout
* about the execution of the internal filters.
* @{
*/
virtual void DebugOn();
virtual void DebugOff();
/**@}*/
/** Get the value of the debug flag.
* @{
*/
virtual bool GetDebug() const;
virtual void SetDebug(bool debugFlag);
/**@}*/
/** Turn default debugging output value on/off.
*
* This is the initial values used for new classes and
* procedural methods.
*/
static void GlobalDefaultDebugOn();
static void GlobalDefaultDebugOff();
/**@}*/
/** Get the value of the default debug flag. */
static bool GetGlobalDefaultDebug();
static void SetGlobalDefaultDebug(bool debugFlag);
/**@}*/
/** Manage warnings produced by ITK.
*
* Enabled by default, this parameter may enable printing
* of warnings indicating unstable state or parameters during
* execution. It is a global value set for all ITK filters and
* processes.
* @{
*/
static void GlobalWarningDisplayOn();
static void GlobalWarningDisplayOff();
static void SetGlobalWarningDisplay(bool flag);
static bool GetGlobalWarningDisplay();
/**@}*/
/** Set the number of threads that all new process objects are
* initialized with.
* @{
*/
static void SetGlobalDefaultNumberOfThreads(unsigned int n);
static unsigned int GetGlobalDefaultNumberOfThreads();
/**@}*/
/** \brief Access the global tolerance to determine congruent spaces.
*
* The default tolerance is governed by the
* GlobalDefaultCoordinateTolerance and the
* GlobalDefaultDirectionTolerance properties, defaulting to
* 1.0e-6. The default tolerance for spatial comparison is then
* scaled by the voxelSpacing for coordinates (i.e. the
* coordinates must be the same to within one part per
* million). For the direction cosines the values must be within
* the current absolute tolerance.
* @{
*/
static double GetGlobalDefaultCoordinateTolerance();
static void SetGlobalDefaultCoordinateTolerance(double );
static double GetGlobalDefaultDirectionTolerance();
static void SetGlobalDefaultDirectionTolerance(double);
/**@}*/
/** The number of threads used when executing a filter if the
* filter is multi-threaded
* @{
*/
virtual void SetNumberOfThreads(unsigned int n);
virtual unsigned int GetNumberOfThreads() const;
/**@}*/
/** \brief Add a Command Object to observer the event.
*
* The Command object's Execute method will be invoked when the
* internal ITK Object has the event. These events only occur
* during this ProcessObject's Execute method when the ITK
* filter is running. The command occurs in the same thread as
* this objects Execute methods was called in.
*
* An internal reference is made between the Command and this
* ProcessObject which enable automatic removal of the command
* when deleted. This enables both object to exist as stack
* based object and be automatically cleaned up.
*
* Unless specified otherwise, it's safe to get any value during
* execution. "Measurements" will have valid values only after
* the Execute method has returned. "Active Measurements" will
* have valid values during events, and access the underlying
* ITK object.
*
* Deleting a command this object has during a command call-back
* will produce undefined behavior.
*
* For more information see the page \ref CommandPage.
*
* \note The return value is reserved for latter usage.
*/
virtual int AddCommand(itk::simple::EventEnum event, itk::simple::Command &cmd);
/** \brief Remove all registered commands.
*
* Calling when this object is invoking anther command will
* produce undefined behavior.
*/
virtual void RemoveAllCommands();
/** \brief Query of this object has any registered commands for event. */
virtual bool HasCommand( itk::simple::EventEnum event ) const;
/** \brief An Active Measurement of the progress of execution.
*
* Get the execution progress of the current process object. The
* progress is a floating number in [0,1] with 0 meaning no progress and 1
* meaning the filter has completed execution (or aborted).
*
* This is an Active Measurement so it can be accessed during
* Events during the execution.
*/
virtual float GetProgress( ) const;
/** Sets an abort flag on the active process.
*
* Requests the current active process to abort. Additional,
* progress or iteration event may occur. If aborted then, an
* AbortEvent should occur. The Progress should be set to 1.0
* after aborting.
*
* The expected behavior is that not exception should be throw
* out of this processes Execute method. Additionally, the
* results returned are valid but undefined content. The
* content may be only partially updated, uninitialized or the a
* of size zero.
*
* If there is no active process the method has no effect.
*/
virtual void Abort();
protected:
#ifndef SWIG
struct EventCommand
{
EventCommand(EventEnum e, Command *c)
: m_Event(e), m_Command(c), m_ITKTag(std::numeric_limits<unsigned long>::max())
{}
EventEnum m_Event;
Command * m_Command;
// set to max if currently not registered
unsigned long m_ITKTag;
inline bool operator==(const EventCommand &o) const
{ return m_Command == o.m_Command; }
inline bool operator<(const EventCommand &o) const
{ return m_Command < o.m_Command; }
};
// method called before filter update to set parameters and
// connect commands.
virtual void PreUpdate( itk::ProcessObject *p );
// overridable method to add a command, the return value is
// placed in the m_ITKTag of the EventCommand object.
virtual unsigned long AddITKObserver(const itk::EventObject &, itk::Command *);
// overridable method to remove a command
virtual void RemoveITKObserver( EventCommand &e );
// Create an ITK EventObject from the SimpleITK enumerated type.
static const itk::EventObject &GetITKEventObject(EventEnum e);
// returns the current active process, if no active process then
// an exception is throw.
virtual itk::ProcessObject *GetActiveProcess( );
// overidable callback when the active process has completed
virtual void OnActiveProcessDelete( );
friend class itk::simple::Command;
// method call by command when it's deleted, maintains internal
// references between command and process objects.
virtual void onCommandDelete(const itk::simple::Command *cmd) throw();
#endif
template< class TImageType >
static typename TImageType::ConstPointer CastImageToITK( const Image &img )
{
typename TImageType::ConstPointer itkImage =
dynamic_cast < const TImageType* > ( img.GetITKBase() );
if ( itkImage.IsNull() )
{
sitkExceptionMacro( "Unexpected template dispatch error!" );
}
return itkImage;
}
template< class TImageType >
static Image CastITKToImage( TImageType *img )
{
return Image(img);
}
#ifndef SWIG
template< class TPixelType, unsigned int VImageDimension, unsigned int VLength,
template<typename, unsigned int> class TVector >
static Image CastITKToImage( itk::Image< TVector< TPixelType, VLength >, VImageDimension> *img )
{
typedef itk::VectorImage< TPixelType, VImageDimension > VectorImageType;
size_t numberOfElements = img->GetBufferedRegion().GetNumberOfPixels();
typename VectorImageType::InternalPixelType* buffer = reinterpret_cast<typename VectorImageType::InternalPixelType*>( img->GetPixelContainer()->GetBufferPointer() );
// Unlike an image of Vectors a VectorImage's container is a
// container of TPixelType, whos size is the image's number of
// pixels * number of pixels per component
numberOfElements *= VImageDimension;
typename VectorImageType::Pointer out = VectorImageType::New();
// Set the image's pixel container to import the pointer provided.
out->GetPixelContainer()->SetImportPointer(buffer, numberOfElements, true );
img->GetPixelContainer()->ContainerManageMemoryOff();
out->CopyInformation( img );
out->SetRegions( img->GetBufferedRegion() );
return Image(out.GetPointer());
}
#endif
/**
* Output operator to os with conversion to a printable type.
*
* That is char types are presumed to be numbers, and converted
* to int.
* @{
*/
template <typename T>
static std::ostream & ToStringHelper(std::ostream &os, const T &v)
{
os << v;
return os;
}
static std::ostream & ToStringHelper(std::ostream &os, const char &v);
static std::ostream & ToStringHelper(std::ostream &os, const signed char &v);
static std::ostream & ToStringHelper(std::ostream &os, const unsigned char &v);
/**@}*/
private:
// Add command to active process object, the EventCommand's
// ITKTag must be unset as max or else an exception is
// thrown. The EventCommand's ITKTag is updated to the command
// registered to ITK's ProcessObject. It's assumed that there is
// an current active process
unsigned long AddObserverToActiveProcessObject( EventCommand &e );
// Remove the command from the active processes. Its is assumed
// that an active process exists. The tag is set to max after it
// is removed.
void RemoveObserverFromActiveProcessObject( EventCommand &e );
bool m_Debug;
unsigned int m_NumberOfThreads;
std::list<EventCommand> m_Commands;
itk::ProcessObject *m_ActiveProcess;
//
float m_ProgressMeasurement;
};
}
}
#endif
|