1
/*=========================================================================
3
* Copyright Insight Software Consortium
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
9
* http://www.apache.org/licenses/LICENSE-2.0.txt
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.
17
*=========================================================================*/
18
#include "sitkProcessObject.h"
19
#include "sitkCommand.h"
21
#include "itkProcessObject.h"
22
#include "itkCommand.h"
23
#include "itkImageToImageFilter.h"
28
#include "nsstd/functional.h"
35
static bool GlobalDefaultDebug = false;
37
static itk::AnyEvent eventAnyEvent;
38
static itk::AbortEvent eventAbortEvent;
39
static itk::DeleteEvent eventDeleteEvent;
40
static itk::EndEvent eventEndEvent;;
41
static itk::IterationEvent eventIterationEvent;
42
static itk::ProgressEvent eventProgressEvent;
43
static itk::StartEvent eventStartEvent;
44
static itk::UserEvent eventUserEvent;
45
static itk::MultiResolutionIterationEvent eventMultiResolutionIterationEvent;
48
// Local class to adapt a sitk::Command to ITK's command.
49
// It utilizes a raw pointer, and relies on the sitk
50
// ProcessObject<->Command reference to automatically remove it.
51
class SimpleAdaptorCommand
56
typedef SimpleAdaptorCommand Self;
57
typedef SmartPointer< Self > Pointer;
61
itkTypeMacro(SimpleAdaptorCommand, Command);
63
void SetSimpleCommand( itk::simple::Command *cmd )
68
/** Invoke the member function. */
69
virtual void Execute(Object *, const EventObject & ) SITK_OVERRIDE
77
/** Invoke the member function with a const object */
78
virtual void Execute(const Object *, const EventObject & ) SITK_OVERRIDE
87
itk::simple::Command * m_That;
88
SimpleAdaptorCommand():m_That(0) {}
89
virtual ~SimpleAdaptorCommand() {}
92
SimpleAdaptorCommand(const Self &); //purposely not implemented
93
void operator=(const Self &); //purposely not implemented
96
} // end anonymous namespace
98
//----------------------------------------------------------------------------
101
// Default constructor that initializes parameters
103
ProcessObject::ProcessObject ()
104
: m_Debug(ProcessObject::GetGlobalDefaultDebug()),
105
m_NumberOfThreads(ProcessObject::GetGlobalDefaultNumberOfThreads()),
106
m_ActiveProcess(NULL),
107
m_ProgressMeasurement(0.0)
115
ProcessObject::~ProcessObject ()
117
// ensure to remove reference between sitk commands and process object
118
Self::RemoveAllCommands();
121
std::string ProcessObject::ToString() const
123
std::ostringstream out;
126
this->ToStringHelper(out, this->m_Debug) << std::endl;
128
out << " NumberOfThreads: ";
129
this->ToStringHelper(out, this->m_NumberOfThreads) << std::endl;
131
out << " Commands:" << (m_Commands.empty()?" (none)":"") << std::endl;
132
for( std::list<EventCommand>::const_iterator i = m_Commands.begin();
133
i != m_Commands.end();
136
assert( i->m_Command );
137
out << " Event: " << i->m_Event << " Command: " << i->m_Command->GetName() << std::endl;
140
out << " ProgressMeasurement: ";
141
this->ToStringHelper(out, this->m_ProgressMeasurement) << std::endl;
143
out << " ActiveProcess:" << (this->m_ActiveProcess?"":" (none)") <<std::endl;
144
if( this->m_ActiveProcess )
146
this->m_ActiveProcess->Print(out, itk::Indent(4));
153
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const char &v)
160
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const signed char &v)
167
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const unsigned char &v)
174
void ProcessObject::DebugOn()
176
this->m_Debug = true;
180
void ProcessObject::DebugOff()
182
this->m_Debug = false;
186
bool ProcessObject::GetDebug() const
188
return this->m_Debug;
192
void ProcessObject::SetDebug(bool debugFlag)
194
this->m_Debug = debugFlag;
198
void ProcessObject::GlobalDefaultDebugOn()
200
GlobalDefaultDebug = true;
204
void ProcessObject::GlobalDefaultDebugOff()
207
GlobalDefaultDebug = false;
211
bool ProcessObject::GetGlobalDefaultDebug()
213
return GlobalDefaultDebug;
217
void ProcessObject::SetGlobalDefaultDebug(bool debugFlag)
219
GlobalDefaultDebug = debugFlag;
223
void ProcessObject::GlobalWarningDisplayOn()
225
itk::Object::GlobalWarningDisplayOn();
229
void ProcessObject::GlobalWarningDisplayOff()
231
itk::Object::GlobalWarningDisplayOff();
235
bool ProcessObject::GetGlobalWarningDisplay()
237
return itk::Object::GetGlobalWarningDisplay();
241
void ProcessObject::SetGlobalWarningDisplay(bool flag)
243
itk::Object::SetGlobalWarningDisplay(flag);
247
double ProcessObject::GetGlobalDefaultCoordinateTolerance()
249
return itk::ImageToImageFilterCommon::GetGlobalDefaultCoordinateTolerance();
252
void ProcessObject::SetGlobalDefaultCoordinateTolerance(double tolerance)
254
return itk::ImageToImageFilterCommon::SetGlobalDefaultCoordinateTolerance(tolerance);
257
double ProcessObject::GetGlobalDefaultDirectionTolerance()
259
return itk::ImageToImageFilterCommon::GetGlobalDefaultDirectionTolerance();
262
void ProcessObject::SetGlobalDefaultDirectionTolerance(double tolerance)
264
return itk::ImageToImageFilterCommon::SetGlobalDefaultDirectionTolerance(tolerance);
268
void ProcessObject::SetGlobalDefaultNumberOfThreads(unsigned int n)
270
MultiThreader::SetGlobalDefaultNumberOfThreads(n);
274
unsigned int ProcessObject::GetGlobalDefaultNumberOfThreads()
276
return MultiThreader::GetGlobalDefaultNumberOfThreads();
280
void ProcessObject::SetNumberOfThreads(unsigned int n)
282
m_NumberOfThreads = n;
286
unsigned int ProcessObject::GetNumberOfThreads() const
288
return m_NumberOfThreads;
292
int ProcessObject::AddCommand(EventEnum event, Command &cmd)
294
// add to our list of event, command pairs
295
m_Commands.push_back(EventCommand(event,&cmd));
297
// register ourselves with the command
298
cmd.AddProcessObject(this);
300
if (this->m_ActiveProcess)
302
this->AddObserverToActiveProcessObject( m_Commands.back() );
306
m_Commands.back().m_ITKTag = std::numeric_limits<unsigned long>::max();
313
void ProcessObject::RemoveAllCommands()
315
// set's the m_Commands to an empty list via a swap
316
std::list<EventCommand> oldCommands;
317
swap(oldCommands, m_Commands);
319
// remove commands from active process object
320
std::list<EventCommand>::iterator i = oldCommands.begin();
321
while( i != oldCommands.end() && this->m_ActiveProcess )
323
this->RemoveObserverFromActiveProcessObject(*i);
327
// we must only call RemoveProcessObject once for each command
328
// so make a unique list of the Commands.
330
oldCommands.unique();
331
i = oldCommands.begin();
332
while( i != oldCommands.end() )
334
// note: this may call onCommandDelete, but we have already copied
335
// this->m_Command will be empty
336
i++->m_Command->RemoveProcessObject(this);
341
bool ProcessObject::HasCommand( EventEnum event ) const
343
std::list<EventCommand>::const_iterator i = m_Commands.begin();
344
while( i != m_Commands.end() )
346
if (i->m_Event == event)
356
float ProcessObject::GetProgress( ) const
358
if ( this->m_ActiveProcess )
360
return this->m_ActiveProcess->GetProgress();
362
return m_ProgressMeasurement;
366
void ProcessObject::Abort()
368
if ( this->m_ActiveProcess )
370
this->m_ActiveProcess->AbortGenerateDataOn();
375
void ProcessObject::PreUpdate(itk::ProcessObject *p)
379
// propagate number of threads
380
p->SetNumberOfThreads(this->GetNumberOfThreads());
384
this->m_ActiveProcess = p;
386
// add command on active process deletion
387
itk::SimpleMemberCommand<Self>::Pointer onDelete = itk::SimpleMemberCommand<Self>::New();
388
onDelete->SetCallbackFunction(this, &Self::OnActiveProcessDelete);
389
p->AddObserver(itk::DeleteEvent(), onDelete);
392
for (std::list<EventCommand>::iterator i = m_Commands.begin();
393
i != m_Commands.end();
396
this->AddObserverToActiveProcessObject(*i);
402
this->m_ActiveProcess = NULL;
406
if (this->GetDebug())
408
std::cout << "Executing ITK filter:" << std::endl;
414
unsigned long ProcessObject::AddITKObserver( const itk::EventObject &e,
417
assert(this->m_ActiveProcess);
418
return this->m_ActiveProcess->AddObserver(e,c);
422
void ProcessObject::RemoveITKObserver( EventCommand &e )
424
assert(this->m_ActiveProcess);
425
this->m_ActiveProcess->RemoveObserver(e.m_ITKTag);
430
const itk::EventObject &ProcessObject::GetITKEventObject(EventEnum e)
435
return eventAnyEvent;
437
return eventAbortEvent;
438
case sitkDeleteEvent:
439
return eventDeleteEvent;
441
return eventEndEvent;
442
case sitkIterationEvent:
443
return eventIterationEvent;
444
case sitkProgressEvent:
445
return eventProgressEvent;
447
return eventStartEvent;
449
return eventUserEvent;
450
case sitkMultiResolutionIterationEvent:
451
return eventMultiResolutionIterationEvent;
453
sitkExceptionMacro("LogicError: Unexpected event case!");
458
itk::ProcessObject *ProcessObject::GetActiveProcess( )
460
if (this->m_ActiveProcess)
462
return this->m_ActiveProcess;
464
sitkExceptionMacro("No active process for \"" << this->GetName() << "\"!");
468
void ProcessObject::OnActiveProcessDelete( )
470
if (this->m_ActiveProcess)
472
this->m_ProgressMeasurement = this->m_ActiveProcess->GetProgress();
476
this->m_ProgressMeasurement = 0.0f;
479
// clear registered command IDs
480
for (std::list<EventCommand>::iterator i = m_Commands.begin();
481
i != m_Commands.end();
484
i->m_ITKTag = std::numeric_limits<unsigned long>::max();
487
this->m_ActiveProcess = NULL;
491
void ProcessObject::onCommandDelete(const itk::simple::Command *cmd) throw()
493
// remove command from m_Command book keeping list, and remove it
494
// from the ITK ProcessObject
495
std::list<EventCommand>::iterator i = this->m_Commands.begin();
496
while ( i != this->m_Commands.end() )
498
if ( cmd == i->m_Command )
500
if ( this->m_ActiveProcess )
502
this->RemoveObserverFromActiveProcessObject( *i );
504
this->m_Commands.erase(i++);
514
unsigned long ProcessObject::AddObserverToActiveProcessObject( EventCommand &eventCommand )
516
assert( this->m_ActiveProcess );
518
if (eventCommand.m_ITKTag != std::numeric_limits<unsigned long>::max())
520
sitkExceptionMacro("Commands already registered to another process object!");
523
const itk::EventObject &itkEvent = GetITKEventObject(eventCommand.m_Event);
525
// adapt sitk command to itk command
526
SimpleAdaptorCommand::Pointer itkCommand = SimpleAdaptorCommand::New();
527
itkCommand->SetSimpleCommand(eventCommand.m_Command);
528
itkCommand->SetObjectName(eventCommand.m_Command->GetName()+" "+itkEvent.GetEventName());
530
return eventCommand.m_ITKTag = this->AddITKObserver( itkEvent, itkCommand );
533
void ProcessObject::RemoveObserverFromActiveProcessObject( EventCommand &e )
535
assert( this->m_ActiveProcess );
537
if (e.m_ITKTag != std::numeric_limits<unsigned long>::max() )
539
this->RemoveITKObserver(e);
540
e.m_ITKTag = std::numeric_limits<unsigned long>::max();
545
} // end namespace simple
546
} // end namespace itk