]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/ProcessObject.cxx
Moved to version 1.0
[cpPlugins.git] / lib / cpPlugins / ProcessObject.cxx
index 136b45cd3f6a734529b72dacf40525aa251fd74b..0c6b45cb3ae9fe691294a43eacab68b81e1339a3 100644 (file)
+// =========================================================================
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// =========================================================================
+
 #include <cpPlugins/ProcessObject.h>
-#include <cpPlugins/ParametersQtDialog.h>
-#include <itkProcessObject.h>
-#include <chrono>
+#include <cpPlugins/DataObject.h>
+#include <cpPlugins/Pipeline.h>
+#include <boost/property_tree/ptree.hpp>
 
 // -------------------------------------------------------------------------
-cpPlugins::Parameters* cpPlugins::ProcessObject::
-GetParameters( )
+const std::string& cpPlugins::ProcessObject::
+GetName( ) const
 {
-  return( &( this->m_Parameters ) );
+  return( this->m_Name );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::Parameters* cpPlugins::ProcessObject::
-GetParameters( ) const
+void cpPlugins::ProcessObject::
+SetName( const std::string& name )
 {
-  return( &( this->m_Parameters ) );
+  if( this->m_Name != name )
+  {
+    this->m_Name = name;
+    this->Modified( );
+  } // end if
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::ProcessObject::
-SetITK( itk::LightObject* o )
+Print( std::ostream& o ) const
 {
-  // Polymorphism: do nothing -> this is a filter!!!
+  this->Superclass::Print( o );
+  this->TParameters::Print( o );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::ProcessObject::
-SetVTK( vtkObjectBase* o )
+SetPipeline( cpPlugins::Pipeline* p )
 {
-  // Polymorphism: do nothing -> this is a filter!!!
+  if( p != NULL )
+    this->m_Pipeline = p->CastWeakPtr< cpPlugins::Pipeline >( );
+  else
+    this->m_Pipeline.reset( );
 }
 
 // -------------------------------------------------------------------------
-std::set< std::string > cpPlugins::ProcessObject::
-GetInputsNames( ) const
+void cpPlugins::ProcessObject::
+SetInput( const std::string& name, cpPlugins::DataObject* data )
+{
+  TInputs::iterator i = this->m_Inputs.find( name );
+  if( i != this->m_Inputs.end( ) )
+  {
+    if( !( i->second.Set( data ) ) )
+      cpPluginsErrorMacro(
+        this, << "Input \"" << name << "\" does not match to input data."
+        );
+  }
+  else
+    cpPluginsErrorMacro(
+      this, << "Input \"" << name << "\" does not belong to this filter."
+      );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::DataObject* cpPlugins::ProcessObject::
+GetInput( const std::string& name, const unsigned int id )
+{
+  TInputs::iterator i = this->m_Inputs.find( name );
+  if( i != this->m_Inputs.end( ) )
+  {
+    if( id < i->second.Count( ) )
+      return( i->second.Get( id ) );
+    else
+      cpPluginsErrorMacro(
+        this, << "Input \"" << name << "\" does have enough inputs."
+        );
+  }
+  else
+    cpPluginsErrorMacro(
+      this, << "Input \"" << name << "\" does not belong to this filter."
+      );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::DataObject* cpPlugins::ProcessObject::
+GetInput( const std::string& name, const unsigned int id ) const
 {
-  std::set< std::string > names;
-  for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i )
-    names.insert( i->first );
-  return( names );
+  TInputs::const_iterator i = this->m_Inputs.find( name );
+  if( i != this->m_Inputs.end( ) )
+  {
+    if( id < i->second.Count( ) )
+      return( i->second.Get( id ) );
+    else
+      cpPluginsErrorMacro(
+        this, << "Input \"" << name << "\" does have enough inputs."
+        );
+  }
+  else
+    cpPluginsErrorMacro(
+      this, << "Input \"" << name << "\" does not belong to this filter."
+      );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::ProcessObject::
+HasInput( const std::string& name ) const
+{
+  TInputs::const_iterator i = this->m_Inputs.find( name );
+  return( i != this->m_Inputs.end( ) );
 }
 
 // -------------------------------------------------------------------------
 std::set< std::string > cpPlugins::ProcessObject::
-GetOutputsNames( ) const
+GetInputsNames( ) const
 {
-  std::set< std::string > names;
-  for( auto i = this->m_Outputs.begin( ); i != this->m_Outputs.end( ); ++i )
-    names.insert( i->first );
-  return( names );
+  std::set< std::string > n;
+  TInputs::const_iterator i = this->m_Inputs.begin( );
+  for( ; i != this->m_Inputs.end( ); ++i )
+    n.insert( i->first );
+  return( n );
 }
 
 // -------------------------------------------------------------------------
@@ -60,244 +129,252 @@ GetNumberOfInputs( ) const
 
 // -------------------------------------------------------------------------
 unsigned int cpPlugins::ProcessObject::
-GetNumberOfOutputs( ) const
+GetNumberOfInputs( const std::string& name ) const
 {
-  return( this->m_Outputs.size( ) );
+  TInputs::const_iterator i = this->m_Inputs.find( name );
+  if( i != this->m_Inputs.end( ) )
+    return( i->second.Count( ) );
+  else
+    return( 0 );
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::
-OutputPort& cpPlugins::ProcessObject::
-GetOutput( const std::string& id )
+std::set< std::string > cpPlugins::ProcessObject::
+GetAllInputsNames( ) const
 {
-  static OutputPort null_port;
-  auto i = this->m_Outputs.find( id );
-  if( i == this->m_Outputs.end( ) )
-  {
-    null_port = NULL;
-    return( null_port );
-  }
-  else
-    return( i->second );
+  std::set< std::string > r = this->GetInputsNames( );
+  std::set< std::string > iScalar = this->GetInValueNames( );
+  std::set< std::string > iSet = this->GetInSetNames( );
+  std::set< std::string > iSequence = this->GetInSequenceNames( );
+  for( const std::string& s: iScalar )
+    r.insert( s );
+  for( const std::string& s: iSet )
+    r.insert( s );
+  for( const std::string& s: iSequence )
+    r.insert( s );
+
+  return( r );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::
-OutputPort& cpPlugins::ProcessObject::
-GetOutput( const std::string& id ) const
+std::set< std::string > cpPlugins::ProcessObject::
+GetAllOutputsNames( ) const
 {
-  static const OutputPort null_port;
-  auto i = this->m_Outputs.find( id );
-  if( i == this->m_Outputs.end( ) )
-    return( null_port );
-  else
-    return( i->second );
+  std::set< std::string > r = this->GetOutValueNames( );
+  std::set< std::string > oSet = this->GetOutSetNames( );
+  std::set< std::string > oSequence = this->GetOutSequenceNames( );
+  for( const std::string& s: oSet )
+    r.insert( s );
+  for( const std::string& s: oSequence )
+    r.insert( s );
+
+  return( r );
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::
-DataObject* cpPlugins::ProcessObject::
-GetInputData( const std::string& id )
+bool cpPlugins::ProcessObject::
+GetExecutionDebug( ) const
 {
-  auto i = this->m_Inputs.find( id );
-  if( i != this->m_Inputs.end( ) )
-    return( dynamic_cast< DataObject* >( i->second.GetPointer( ) ) );
-  else
-    return( NULL );
+  return( this->m_ExecutionDebug );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::
-DataObject* cpPlugins::ProcessObject::
-GetInputData( const std::string& id ) const
+void cpPlugins::ProcessObject::
+SetExecutionDebug( bool d )
 {
-  auto i = this->m_Inputs.find( id );
-  if( i != this->m_Inputs.end( ) )
-    return( dynamic_cast< const DataObject* >( i->second.GetPointer( ) ) );
-  else
-    return( NULL );
+  this->m_ExecutionDebug = d;
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::
-DataObject* cpPlugins::ProcessObject::
-GetOutputData( const std::string& id )
+void cpPlugins::ProcessObject::
+ExecutionDebugOn( )
 {
-  auto i = this->m_Outputs.find( id );
-  if( i != this->m_Outputs.end( ) )
-    return( dynamic_cast< DataObject* >( i->second.GetPointer( ) ) );
-  else
-    return( NULL );
+  this->SetExecutionDebug( true );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::
-DataObject* cpPlugins::ProcessObject::
-GetOutputData( const std::string& id ) const
+void cpPlugins::ProcessObject::
+ExecutionDebugOff( )
 {
-  auto i = this->m_Outputs.find( id );
-  if( i != this->m_Outputs.end( ) )
-    return( dynamic_cast< const DataObject* >( i->second.GetPointer( ) ) );
-  else
-    return( NULL );
+  this->SetExecutionDebug( false );
+}
+
+// -------------------------------------------------------------------------
+const double& cpPlugins::ProcessObject::
+GetLastDuration( ) const
+{
+  return( this->m_LastDuration );
 }
 
 // -------------------------------------------------------------------------
 bool cpPlugins::ProcessObject::
-SetInput( const std::string& id, const OutputPort& port )
+IsUpdated( const TTimeStamp& d ) const
 {
-  auto i = this->m_Inputs.find( id );
-  if( i != this->m_Inputs.end( ) )
+  bool ok = this->Superclass::IsUpdated( d );
+  if( ok )
   {
-    if( i->second.GetPointer( ) != port.GetPointer( ) )
+    for( const TInputs::value_type& i: this->m_Inputs )
     {
-      i->second = port;
-      this->Modified( );
+      for( unsigned long j = 0; j < i.second.Count( ); ++j )
+      {
+        const cpPlugins::DataObject* dObj = i.second.Get( j );
+        if( dObj != NULL )
+          ok &= dObj->IsUpdated( d );
+
+      } // end for
+    } // end for
+  } // end if
+  return( ok );
+}
 
-    } // fi
-    return( true );
-  }
-  else
-    return( false );
+// -------------------------------------------------------------------------
+void cpPlugins::ProcessObject::
+Modified( )
+{
+  this->m_LastDuration = -1;
+  this->Superclass::Modified( );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::ProcessObject::
-DisconnectInputs( )
+ModifiedInValue( const std::string& name )
 {
-  auto i = this->m_Inputs.begin( );
-  for( ; i != this->m_Inputs.end( ); ++i )
-    i->second = NULL;
+  // WARNING: Synch parameters in cpPlugins::Pipeline
   this->Modified( );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::ProcessObject::
-DisconnectOutputs( )
+ModifiedInSet( const std::string& name )
 {
-  auto i = this->m_Outputs.begin( );
-  for( ; i != this->m_Outputs.end( ); ++i )
-    if( i->second.IsValid( ) )
-      i->second->DisconnectFromPipeline( );
+  // WARNING: Synch parameters in cpPlugins::Pipeline
   this->Modified( );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::ProcessObject::
-Disconnect( )
+ModifiedInSequence( const std::string& name )
 {
-  this->DisconnectInputs( );
-  this->DisconnectOutputs( );
+  // WARNING: Synch parameters in cpPlugins::Pipeline
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-itk::ModifiedTimeType cpPlugins::ProcessObject::
-GetMTime( ) const
+void cpPlugins::ProcessObject::
+ModifiedOutValue( const std::string& name )
 {
-  auto params_time = this->m_Parameters.GetMTime( );
-  auto filter_time = this->Superclass::GetMTime( );
-  return( ( params_time > filter_time )? params_time: filter_time );
+  // WARNING: Synch parameters in cpPlugins::Pipeline
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-std::string cpPlugins::ProcessObject::
-Update( )
+void cpPlugins::ProcessObject::
+ModifiedOutSet( const std::string& name )
 {
-  std::string r = "";
-
-  // Force upstream updates
-  auto i = this->m_Inputs.begin( );
-  bool need_to_update = false;
-  for( ; i != this->m_Inputs.end( ) && r == ""; ++i )
-  {
-    bool iv = i->second.IsValid( );
-    bool ir = i->second.IsRequired( );
-    if( !iv && ir )
-      r =
-        "ProcessObject: Required input \"" +
-        i->first + "@" + this->GetClassName( ) +
-        "\" is not valid (=NULL).";
-    if( iv && r == "" )
-    {
-      Self* src = dynamic_cast< Self* >( i->second->GetSource( ) );
-      if( src != NULL )
-      {
-        need_to_update |= ( this->m_LastExecutionTime < src->GetMTime( ) );
-        r = src->Update( );
-
-      } // fi
-
-    } // fi
-
-  } // rof
-
-  // Current update
-  if( r == "" )
-  {
-    if( this->m_LastExecutionTime < this->GetMTime( ) || need_to_update )
-    {
-      std::cout
-        << "cpPlugins: Updating \""
-        << this->GetClassName( ) << ":" << this->GetClassCategory( )
-        << "\"... ";
-      std::cout.flush( );
-      long start =
-        std::chrono::duration_cast< std::chrono::milliseconds >(
-          std::chrono::system_clock::now( ).time_since_epoch( )
-          ).count( );
-      r = this->_GenerateData( );
-      long end =
-        std::chrono::duration_cast< std::chrono::milliseconds >(
-          std::chrono::system_clock::now( ).time_since_epoch( )
-          ).count( );
-      this->m_LastExecutionTime = this->GetMTime( );
-      std::cout << "done in " << ( ( end - start ) / 1000 ) << "ms!" << std::endl;
-
-    } // fi
-
-  } // fi
-
-  // Return error description, if any
-  return( r );
+  // WARNING: Synch parameters in cpPlugins::Pipeline
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::ParametersQtDialog* cpPlugins::ProcessObject::
-CreateQtDialog( )
+void cpPlugins::ProcessObject::
+ModifiedOutSequence( const std::string& name )
 {
-#ifdef cpPlugins_QT4
-  ParametersQtDialog* dlg = NULL;
-  if( QApplication::instance( ) != NULL )
-  {
-    dlg = new ParametersQtDialog( );
-    dlg->setProcessObject( this );
+  // WARNING: Synch parameters in cpPlugins::Pipeline
+  this->Modified( );
+}
 
-  } // fi
-  return( dlg );
-#else // cpPlugins_QT4  
-  return( NULL );
-#endif // cpPlugins_QT4
+// -------------------------------------------------------------------------
+void cpPlugins::ProcessObject::
+ModifiedChoice( const std::string& name )
+{
+  // WARNING: Synch parameters in cpPlugins::Pipeline
+  this->Modified( );
 }
 
 // -------------------------------------------------------------------------
-bool cpPlugins::ProcessObject::
-IsInteractive( )
+void cpPlugins::ProcessObject::
+Update( )
 {
-  return( false );
+  bool is_updated = this->IsUpdated( );
+  is_updated &= this->TParameters::Update( );
+
+  // Check inputs
+  for( TInputs::value_type i: this->m_Inputs )
+  {
+    if( i.second.IsValid( ) )
+    {
+      for( unsigned long j = 0; j < i.second.Count( ); ++j )
+      {
+        cpPlugins::DataObject* dObj = i.second.Get( j );
+        if( dObj )
+        {
+          if( !( dObj->IsUpdated( ) ) )
+          {
+            dObj->Update( );
+            is_updated = false;
+
+          } // end if
+        } // end if
+      } // end for
+    } // end if
+  } // end for
+
+  // Allow some updates in particular cases (i.e. Functors)
+  is_updated &= this->_BeforeUpdate( );
+
+  // Update outputs
+  if( !is_updated )
+  {
+    if( this->m_ExecutionDebug )
+    {
+      *( this->m_OutStream )
+        << "Executing node \"" << this->GetName( ) << "\"... "
+        << std::ends;
+      this->m_OutStream->flush( );
+    } // end if
+    std::chrono::steady_clock::time_point start =
+      std::chrono::steady_clock::now( );
+    this->_GenerateData( );
+    std::chrono::steady_clock::time_point end =
+      std::chrono::steady_clock::now( );
+    this->m_LastDuration =
+      double(
+        std::chrono::duration_cast< std::chrono::microseconds >(
+        end - start
+          ).count( )
+        ) * 1e-6;
+    if( this->m_ExecutionDebug )
+    {
+      *( this->m_OutStream )
+        << "done in "
+        << this->m_LastDuration << " s"
+        << std::endl;
+      this->m_OutStream->flush( );
+    } // end if
+    this->_SynchTime( );
+  } // end if
 }
 
 // -------------------------------------------------------------------------
+template< >
 void cpPlugins::ProcessObject::
-SetInteractionObjects( const std::vector< void* >& objs )
+SaveXML( boost::property_tree::ptree* node ) const
 {
-  // Do nothing
+  boost::property_tree::ptree xml;
+  xml.put( "<xmlattr>.name", this->GetName( ) );
+  xml.put( "<xmlattr>.class", this->GetClassName( ) );
+  this->TParameters::SaveXML( &xml );
+  node->add_child( "pipeline.node", xml );
 }
 
 // -------------------------------------------------------------------------
 cpPlugins::ProcessObject::
 ProcessObject( )
   : Superclass( ),
-    m_LastExecutionTime( 0 )
+    TParameters( ),
+    m_OutStream( &std::cout ),
+    m_ExecutionDebug( false ),
+    m_LastDuration( -1 )
 {
 }
 
@@ -308,16 +385,10 @@ cpPlugins::ProcessObject::
 }
 
 // -------------------------------------------------------------------------
-void cpPlugins::ProcessObject::
-_AddInput( const std::string& name, bool required )
+bool cpPlugins::ProcessObject::
+_BeforeUpdate( )
 {
-  auto i = this->m_Inputs.find( name );
-  if( i == this->m_Inputs.end( ) )
-  {
-    this->m_Inputs[ name ] = InputPort( required );
-    this->Modified( );
-
-  } // fi
+  return( true );
 }
 
 // eof - $RCSfile$