~ubuntu-branches/debian/sid/simpleitk/sid

« back to all changes in this revision

Viewing changes to Code/Common/src/sitkProcessObject.cxx

  • Committer: Package Import Robot
  • Author(s): Ghislain Antony Vaillant
  • Date: 2017-11-02 08:49:18 UTC
  • Revision ID: package-import@ubuntu.com-20171102084918-7hs09ih668xq87ej
Tags: upstream-1.0.1
ImportĀ upstreamĀ versionĀ 1.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "sitkProcessObject.h"
 
19
#include "sitkCommand.h"
 
20
 
 
21
#include "itkProcessObject.h"
 
22
#include "itkCommand.h"
 
23
#include "itkImageToImageFilter.h"
 
24
 
 
25
#include <iostream>
 
26
#include <algorithm>
 
27
 
 
28
#include "nsstd/functional.h"
 
29
 
 
30
namespace itk {
 
31
namespace simple {
 
32
 
 
33
namespace
 
34
{
 
35
static bool GlobalDefaultDebug = false;
 
36
 
 
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;
 
46
 
 
47
 
 
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
 
52
  : public itk::Command
 
53
{
 
54
public:
 
55
 
 
56
  typedef SimpleAdaptorCommand Self;
 
57
  typedef SmartPointer< Self >  Pointer;
 
58
 
 
59
  itkNewMacro(Self);
 
60
 
 
61
  itkTypeMacro(SimpleAdaptorCommand, Command);
 
62
 
 
63
  void SetSimpleCommand( itk::simple::Command *cmd )
 
64
    {
 
65
      m_That=cmd;
 
66
    }
 
67
 
 
68
  /**  Invoke the member function. */
 
69
  virtual void Execute(Object *, const EventObject & ) SITK_OVERRIDE
 
70
  {
 
71
    if (m_That)
 
72
      {
 
73
      m_That->Execute();
 
74
      }
 
75
  }
 
76
 
 
77
  /**  Invoke the member function with a const object */
 
78
  virtual void Execute(const Object *, const EventObject & ) SITK_OVERRIDE
 
79
  {
 
80
    if ( m_That )
 
81
      {
 
82
      m_That->Execute();
 
83
      }
 
84
  }
 
85
 
 
86
protected:
 
87
  itk::simple::Command *                    m_That;
 
88
  SimpleAdaptorCommand():m_That(0) {}
 
89
  virtual ~SimpleAdaptorCommand() {}
 
90
 
 
91
private:
 
92
  SimpleAdaptorCommand(const Self &); //purposely not implemented
 
93
  void operator=(const Self &);        //purposely not implemented
 
94
};
 
95
 
 
96
} // end anonymous namespace
 
97
 
 
98
//----------------------------------------------------------------------------
 
99
 
 
100
//
 
101
// Default constructor that initializes parameters
 
102
//
 
103
ProcessObject::ProcessObject ()
 
104
  : m_Debug(ProcessObject::GetGlobalDefaultDebug()),
 
105
    m_NumberOfThreads(ProcessObject::GetGlobalDefaultNumberOfThreads()),
 
106
    m_ActiveProcess(NULL),
 
107
    m_ProgressMeasurement(0.0)
 
108
{
 
109
}
 
110
 
 
111
 
 
112
//
 
113
// Destructor
 
114
//
 
115
ProcessObject::~ProcessObject ()
 
116
{
 
117
  // ensure to remove reference between sitk commands and process object
 
118
  Self::RemoveAllCommands();
 
119
}
 
120
 
 
121
std::string ProcessObject::ToString() const
 
122
{
 
123
  std::ostringstream out;
 
124
 
 
125
  out << "  Debug: ";
 
126
  this->ToStringHelper(out, this->m_Debug) << std::endl;
 
127
 
 
128
  out << "  NumberOfThreads: ";
 
129
  this->ToStringHelper(out, this->m_NumberOfThreads) << std::endl;
 
130
 
 
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();
 
134
       ++i)
 
135
    {
 
136
    assert( i->m_Command );
 
137
    out << "    Event: " << i->m_Event << " Command: " << i->m_Command->GetName() << std::endl;
 
138
    }
 
139
 
 
140
  out << "  ProgressMeasurement: ";
 
141
  this->ToStringHelper(out, this->m_ProgressMeasurement) << std::endl;
 
142
 
 
143
  out << "  ActiveProcess:" << (this->m_ActiveProcess?"":" (none)") <<std::endl;
 
144
  if( this->m_ActiveProcess )
 
145
    {
 
146
    this->m_ActiveProcess->Print(out, itk::Indent(4));
 
147
    }
 
148
 
 
149
  return out.str();
 
150
}
 
151
 
 
152
 
 
153
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const char &v)
 
154
{
 
155
  os << int(v);
 
156
  return os;
 
157
}
 
158
 
 
159
 
 
160
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const signed char &v)
 
161
{
 
162
  os << int(v);
 
163
  return os;
 
164
}
 
165
 
 
166
 
 
167
std::ostream & ProcessObject::ToStringHelper(std::ostream &os, const unsigned char &v)
 
168
{
 
169
  os << int(v);
 
170
  return os;
 
171
}
 
172
 
 
173
 
 
174
void ProcessObject::DebugOn()
 
175
{
 
176
  this->m_Debug = true;
 
177
}
 
178
 
 
179
 
 
180
void ProcessObject::DebugOff()
 
181
{
 
182
  this->m_Debug = false;
 
183
}
 
184
 
 
185
 
 
186
bool ProcessObject::GetDebug() const
 
187
{
 
188
  return this->m_Debug;
 
189
}
 
190
 
 
191
 
 
192
void ProcessObject::SetDebug(bool debugFlag)
 
193
{
 
194
  this->m_Debug = debugFlag;
 
195
}
 
196
 
 
197
 
 
198
void ProcessObject::GlobalDefaultDebugOn()
 
199
{
 
200
  GlobalDefaultDebug = true;
 
201
}
 
202
 
 
203
 
 
204
void ProcessObject::GlobalDefaultDebugOff()
 
205
 
 
206
{
 
207
  GlobalDefaultDebug = false;
 
208
}
 
209
 
 
210
 
 
211
bool ProcessObject::GetGlobalDefaultDebug()
 
212
{
 
213
  return GlobalDefaultDebug;
 
214
}
 
215
 
 
216
 
 
217
void ProcessObject::SetGlobalDefaultDebug(bool debugFlag)
 
218
{
 
219
  GlobalDefaultDebug = debugFlag;
 
220
}
 
221
 
 
222
 
 
223
void ProcessObject::GlobalWarningDisplayOn()
 
224
{
 
225
  itk::Object::GlobalWarningDisplayOn();
 
226
}
 
227
 
 
228
 
 
229
void ProcessObject::GlobalWarningDisplayOff()
 
230
{
 
231
  itk::Object::GlobalWarningDisplayOff();
 
232
}
 
233
 
 
234
 
 
235
bool ProcessObject::GetGlobalWarningDisplay()
 
236
{
 
237
  return itk::Object::GetGlobalWarningDisplay();
 
238
}
 
239
 
 
240
 
 
241
void ProcessObject::SetGlobalWarningDisplay(bool flag)
 
242
{
 
243
  itk::Object::SetGlobalWarningDisplay(flag);
 
244
}
 
245
 
 
246
 
 
247
double ProcessObject::GetGlobalDefaultCoordinateTolerance()
 
248
{
 
249
  return itk::ImageToImageFilterCommon::GetGlobalDefaultCoordinateTolerance();
 
250
}
 
251
 
 
252
void ProcessObject::SetGlobalDefaultCoordinateTolerance(double tolerance)
 
253
{
 
254
  return itk::ImageToImageFilterCommon::SetGlobalDefaultCoordinateTolerance(tolerance);
 
255
}
 
256
 
 
257
double ProcessObject::GetGlobalDefaultDirectionTolerance()
 
258
{
 
259
  return itk::ImageToImageFilterCommon::GetGlobalDefaultDirectionTolerance();
 
260
}
 
261
 
 
262
void ProcessObject::SetGlobalDefaultDirectionTolerance(double tolerance)
 
263
{
 
264
  return itk::ImageToImageFilterCommon::SetGlobalDefaultDirectionTolerance(tolerance);
 
265
}
 
266
 
 
267
 
 
268
void ProcessObject::SetGlobalDefaultNumberOfThreads(unsigned int n)
 
269
{
 
270
  MultiThreader::SetGlobalDefaultNumberOfThreads(n);
 
271
}
 
272
 
 
273
 
 
274
unsigned int ProcessObject::GetGlobalDefaultNumberOfThreads()
 
275
{
 
276
  return MultiThreader::GetGlobalDefaultNumberOfThreads();
 
277
}
 
278
 
 
279
 
 
280
void ProcessObject::SetNumberOfThreads(unsigned int n)
 
281
{
 
282
  m_NumberOfThreads = n;
 
283
}
 
284
 
 
285
 
 
286
unsigned int ProcessObject::GetNumberOfThreads() const
 
287
{
 
288
  return m_NumberOfThreads;
 
289
}
 
290
 
 
291
 
 
292
int ProcessObject::AddCommand(EventEnum event, Command &cmd)
 
293
{
 
294
  // add to our list of event, command pairs
 
295
  m_Commands.push_back(EventCommand(event,&cmd));
 
296
 
 
297
  // register ourselves with the command
 
298
  cmd.AddProcessObject(this);
 
299
 
 
300
  if (this->m_ActiveProcess)
 
301
    {
 
302
    this->AddObserverToActiveProcessObject( m_Commands.back() );
 
303
    }
 
304
  else
 
305
    {
 
306
    m_Commands.back().m_ITKTag = std::numeric_limits<unsigned long>::max();
 
307
    }
 
308
 
 
309
  return 0;
 
310
}
 
311
 
 
312
 
 
313
void ProcessObject::RemoveAllCommands()
 
314
{
 
315
  // set's the m_Commands to an empty list via a swap
 
316
  std::list<EventCommand> oldCommands;
 
317
  swap(oldCommands, m_Commands);
 
318
 
 
319
  // remove commands from active process object
 
320
  std::list<EventCommand>::iterator i = oldCommands.begin();
 
321
  while( i != oldCommands.end() && this->m_ActiveProcess )
 
322
    {
 
323
    this->RemoveObserverFromActiveProcessObject(*i);
 
324
    ++i;
 
325
    }
 
326
 
 
327
  // we must only call RemoveProcessObject once for each command
 
328
  // so make a unique list of the Commands.
 
329
  oldCommands.sort();
 
330
  oldCommands.unique();
 
331
  i = oldCommands.begin();
 
332
  while( i != oldCommands.end() )
 
333
    {
 
334
    // note: this may call onCommandDelete, but we have already copied
 
335
    // this->m_Command will be empty
 
336
    i++->m_Command->RemoveProcessObject(this);
 
337
    }
 
338
}
 
339
 
 
340
 
 
341
bool ProcessObject::HasCommand( EventEnum event ) const
 
342
{
 
343
  std::list<EventCommand>::const_iterator i = m_Commands.begin();
 
344
  while( i != m_Commands.end() )
 
345
    {
 
346
    if (i->m_Event == event)
 
347
      {
 
348
      return true;
 
349
      }
 
350
    ++i;
 
351
    }
 
352
  return false;
 
353
}
 
354
 
 
355
 
 
356
float ProcessObject::GetProgress( ) const
 
357
{
 
358
  if ( this->m_ActiveProcess )
 
359
    {
 
360
    return this->m_ActiveProcess->GetProgress();
 
361
    }
 
362
  return m_ProgressMeasurement;
 
363
}
 
364
 
 
365
 
 
366
void ProcessObject::Abort()
 
367
{
 
368
  if ( this->m_ActiveProcess )
 
369
    {
 
370
    this->m_ActiveProcess->AbortGenerateDataOn();
 
371
    }
 
372
}
 
373
 
 
374
 
 
375
void ProcessObject::PreUpdate(itk::ProcessObject *p)
 
376
{
 
377
  assert(p);
 
378
 
 
379
  // propagate number of threads
 
380
  p->SetNumberOfThreads(this->GetNumberOfThreads());
 
381
 
 
382
  try
 
383
    {
 
384
    this->m_ActiveProcess = p;
 
385
 
 
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);
 
390
 
 
391
    // register commands
 
392
    for (std::list<EventCommand>::iterator i = m_Commands.begin();
 
393
         i != m_Commands.end();
 
394
         ++i)
 
395
      {
 
396
      this->AddObserverToActiveProcessObject(*i);
 
397
      }
 
398
 
 
399
    }
 
400
  catch (...)
 
401
    {
 
402
    this->m_ActiveProcess = NULL;
 
403
    throw;
 
404
    }
 
405
 
 
406
  if (this->GetDebug())
 
407
     {
 
408
     std::cout << "Executing ITK filter:" << std::endl;
 
409
     p->Print(std::cout);
 
410
     }
 
411
}
 
412
 
 
413
 
 
414
unsigned long ProcessObject::AddITKObserver( const itk::EventObject &e,
 
415
                                             itk::Command *c)
 
416
{
 
417
  assert(this->m_ActiveProcess);
 
418
  return this->m_ActiveProcess->AddObserver(e,c);
 
419
}
 
420
 
 
421
 
 
422
void ProcessObject::RemoveITKObserver( EventCommand &e )
 
423
{
 
424
  assert(this->m_ActiveProcess);
 
425
  this->m_ActiveProcess->RemoveObserver(e.m_ITKTag);
 
426
}
 
427
 
 
428
 
 
429
 
 
430
const itk::EventObject &ProcessObject::GetITKEventObject(EventEnum e)
 
431
{
 
432
  switch (e)
 
433
    {
 
434
    case sitkAnyEvent:
 
435
      return eventAnyEvent;
 
436
    case sitkAbortEvent:
 
437
      return eventAbortEvent;
 
438
    case sitkDeleteEvent:
 
439
      return eventDeleteEvent;
 
440
    case sitkEndEvent:
 
441
      return eventEndEvent;
 
442
    case sitkIterationEvent:
 
443
      return eventIterationEvent;
 
444
    case sitkProgressEvent:
 
445
      return eventProgressEvent;
 
446
    case sitkStartEvent:
 
447
      return eventStartEvent;
 
448
    case sitkUserEvent:
 
449
      return eventUserEvent;
 
450
    case sitkMultiResolutionIterationEvent:
 
451
      return eventMultiResolutionIterationEvent;
 
452
    default:
 
453
      sitkExceptionMacro("LogicError: Unexpected event case!");
 
454
    }
 
455
}
 
456
 
 
457
 
 
458
itk::ProcessObject *ProcessObject::GetActiveProcess( )
 
459
{
 
460
  if (this->m_ActiveProcess)
 
461
    {
 
462
    return this->m_ActiveProcess;
 
463
    }
 
464
  sitkExceptionMacro("No active process for \"" << this->GetName() << "\"!");
 
465
}
 
466
 
 
467
 
 
468
void ProcessObject::OnActiveProcessDelete( )
 
469
{
 
470
  if (this->m_ActiveProcess)
 
471
    {
 
472
    this->m_ProgressMeasurement = this->m_ActiveProcess->GetProgress();
 
473
    }
 
474
  else
 
475
    {
 
476
    this->m_ProgressMeasurement = 0.0f;
 
477
    }
 
478
 
 
479
  // clear registered command IDs
 
480
  for (std::list<EventCommand>::iterator i = m_Commands.begin();
 
481
         i != m_Commands.end();
 
482
         ++i)
 
483
      {
 
484
      i->m_ITKTag = std::numeric_limits<unsigned long>::max();
 
485
      }
 
486
 
 
487
  this->m_ActiveProcess = NULL;
 
488
}
 
489
 
 
490
 
 
491
void ProcessObject::onCommandDelete(const itk::simple::Command *cmd) throw()
 
492
{
 
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() )
 
497
    {
 
498
    if ( cmd == i->m_Command )
 
499
      {
 
500
      if ( this->m_ActiveProcess )
 
501
        {
 
502
        this->RemoveObserverFromActiveProcessObject( *i );
 
503
        }
 
504
      this->m_Commands.erase(i++);
 
505
      }
 
506
    else
 
507
      {
 
508
      ++i;
 
509
      }
 
510
 
 
511
    }
 
512
}
 
513
 
 
514
unsigned long ProcessObject::AddObserverToActiveProcessObject( EventCommand &eventCommand )
 
515
{
 
516
  assert( this->m_ActiveProcess );
 
517
 
 
518
  if (eventCommand.m_ITKTag != std::numeric_limits<unsigned long>::max())
 
519
    {
 
520
    sitkExceptionMacro("Commands already registered to another process object!");
 
521
    }
 
522
 
 
523
  const itk::EventObject &itkEvent = GetITKEventObject(eventCommand.m_Event);
 
524
 
 
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());
 
529
 
 
530
  return eventCommand.m_ITKTag = this->AddITKObserver( itkEvent, itkCommand );
 
531
}
 
532
 
 
533
void ProcessObject::RemoveObserverFromActiveProcessObject( EventCommand &e )
 
534
 {
 
535
   assert( this->m_ActiveProcess );
 
536
 
 
537
   if (e.m_ITKTag != std::numeric_limits<unsigned long>::max() )
 
538
     {
 
539
     this->RemoveITKObserver(e);
 
540
     e.m_ITKTag = std::numeric_limits<unsigned long>::max();
 
541
     }
 
542
 
 
543
 }
 
544
 
 
545
} // end namespace simple
 
546
} // end namespace itk