<commit_before>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdImageViewRenderer.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
#include <QtOpenGL>

//
// System includes (sorted by alphabetic order)
// necessary for the opengl variables and methods

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)
#include "otbStandardShader.h"

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdDatasetModel.h"
#include "Core/mvdTypes.h"
#include "Core/mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::ImageViewRenderer

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*****************************************************************************/
ImageViewRenderer
::ImageViewRenderer( QObject* parent ) :
  AbstractImageViewRenderer( parent ),
  m_GlView( otb::GlView::New() ),
  m_ReferenceImageModel( NULL ),
  m_ReferenceGlImageActor(),
  m_ImageModelActorPairs(),
  m_ReferenceActorShaderMode("STANDARD")
{
  assert( !m_GlView.IsNull() );
}

/*****************************************************************************/
ImageViewRenderer
::~ImageViewRenderer()
{
}

/*****************************************************************************/
bool
ImageViewRenderer
::CheckGLCapabilities() const
{
  qWarning() <<
    ToStdString(
      tr( "Required OpenGL version '%1' with GLSL version '%2'." )
      .arg( otb::GlView::REQUIRED_GL_VERSION )
      .arg( otb::GlView::REQUIRED_GLSL_VERSION )
    ).c_str();

  try
    {
    qWarning() <<
      ToStdString(
        tr( "Runtime OpenGL version '%1' with GLSL version '%2'." )
        .arg( otb::GlView::GLVersion() )
        .arg( otb::GlView::GLSLVersion() )
      ).c_str();
    }
  catch( std::exception& exc )
    {
    qWarning() << ToQString( exc.what() );
    }

  try
    {
    if( otb::GlView::CheckGLCapabilities() )
      return true;

    QMessageBox::critical(
      qobject_cast< QWidget* >( parent() ),
      tr( "Monteverdi2 - Critical error!" ),
      tr( "Current OpenGL version is '%1' supporting GLSL version '%2'.\nRequired OpenGL version is '%3' with Shading-Laguage version '%4'.\nPlease upgrade your graphics driver and hardware for the application to run properly on this platform.\nUsing the application on this platform may lead to unknown behaviour. Would you still like to continue using the application?" )
      .arg( otb::GlView::GLVersion() )
      .arg( otb::GlView::GLSLVersion() )
      .arg( otb::GlView::REQUIRED_GL_VERSION )
      .arg( otb::GlView::REQUIRED_GLSL_VERSION )
    );
    }
  catch( std::exception& exc )
    {
    QMessageBox::critical(
      qobject_cast< QWidget* >( parent() ),
      tr( "Monteverdi2 - Critical error!"),
      ToQString( exc.what() )
    );
    }

  return false;
}

/*****************************************************************************/
AbstractImageViewRenderer::RenderingContext*
ImageViewRenderer
::NewRenderingContext() const
{
  RenderingContext* context = new ImageViewRenderer::RenderingContext();

#if USE_VIEW_SETTINGS_SIDE_EFFECT
#else
  assert( !m_GlView.IsNull() );

  //
  // Share otb::GlViewRendering settings with manipulator using
  // RenderingContext. Manipulator can then setup otb::ViewSettings
  // directly by side-effect.
  context->m_ViewSettings = m_GlView->GetSettings();
#endif

  return context;
}

/*****************************************************************************/
const AbstractImageModel*
ImageViewRenderer
::GetReferenceImageModel() const
{
  return m_ReferenceImageModel;
}

/*****************************************************************************/
AbstractImageModel*
ImageViewRenderer
::GetReferenceImageModel()
{
  return m_ReferenceImageModel;
}

/*****************************************************************************/
void
ImageViewRenderer
::GetReferenceExtent( PointType& origin, PointType& extent  ) const
{
  assert( !m_ReferenceGlImageActor.IsNull() );

  m_ReferenceGlImageActor->GetExtent(
    origin[ 0 ], origin[ 1 ],
    extent[ 0 ], extent[ 1 ]
  );
}

/*****************************************************************************/
void
ImageViewRenderer
::InitializeGL()
{
  assert( !m_GlView.IsNull() );

  //
  // WARNING: This call to otb::GlView::Initialize() allocates a new
  // otb::ViewSettings() instance. So, the shared pointer between
  // renderer and manipulator may be unshated depending on order of
  // calls.
  //
  m_GlView->Initialize( 0, 0 );
}

/*****************************************************************************/
void
ImageViewRenderer
::ResizeGL( int width, int height )
{
  // qDebug() << this << "::ResizeGL(" << width << "," << height << ")";

  /*
  // Should be done here and not in OTB-Ice render routine.
  glViewport(
    0,
    0,
    static_cast< GLint >( width ),
    static_cast< GLint >( height )
  );
  */

  assert( !m_GlView.IsNull() );

  // qDebug() << m_GlView.GetPointer();

  m_GlView->Resize( width, height );

  /*
  glViewport(
    0, 0,
    static_cast< GLint >( width ), static_cast< GLint >( height )
  );

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glOrtho(
    0, static_cast< GLint >( width ),
    0, static_cast< GLint >( height ),
    0, 1
  );
  */
}

/*****************************************************************************/
void
ImageViewRenderer
::PaintGL( const AbstractImageViewRenderer::RenderingContext* c )
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::PaintGL(" << c << ")";

  // qDebug() << m_GlView.GetPointer();

  /*
  //
  // Get appropriate rendering-context.
  assert( c==dynamic_cast< RenderingContext* >( c ) );
  RenderingContext* context = dynamic_cast< RenderingContext* >( c );
  assert( context!=NULL );

  //
  // Set view settings.
  m_GlView->SetSettings( context->m_ViewSettings );
  */

  //
  // Apply VectorImageModel::Settings to otb::GlImageActor.
  UpdateActors( c );

  //
  // Pre-render scene.
  m_GlView->BeforeRendering();
  {
  //
  // Render scene.
  switch( c->m_RenderMode )
    {
    case RenderingContext::RENDER_MODE_LIGHT:
      m_GlView->LightRender();
      break;

    case RenderingContext::RENDER_MODE_FULL:
      m_GlView->HeavyRender();
      break;
    }
  }
  //
  // Post-render scene.
  m_GlView->AfterRendering();
}

/*****************************************************************************/
bool
ImageViewRenderer
::Pick( const PointType& in,
        PointType& out,
        DefaultImageType::PixelType& pixel )
{
  /*
  qDebug()
    << this << "::Pick("
    << in[ 0 ] << "," << in[ 1 ]
    << ")";
  */

  if( m_ReferenceGlImageActor.IsNull() )
    return false;

  //
  // Compute output/physical point.
  out = m_ReferenceGlImageActor->ViewportToImageTransform( in, true );

  //
  // Read pixel value.
  return m_ReferenceGlImageActor->GetPixelFromViewport( in, pixel );
}

/*****************************************************************************/
bool
ImageViewRenderer
::Transform( PointType& point, const IndexType& index, bool isPhysical ) const
{
  if( m_ReferenceGlImageActor.IsNull() )
    return false;

  point[ 0 ] = static_cast< double >( index[ 0 ] );
  point[ 1 ] = static_cast< double >( index[ 1 ] );

  point = m_ReferenceGlImageActor->ImageToViewportTransform( point, isPhysical );

  return true;
}

/*****************************************************************************/
void
ImageViewRenderer
::UpdateActors( const AbstractImageViewRenderer::RenderingContext* )
{
  UpdateImageActors();
}

/*****************************************************************************/
void
ImageViewRenderer
::UpdateImageActors()
{
  for( ImageModelActorPairMap::const_iterator it(m_ImageModelActorPairs.begin());
       it!=m_ImageModelActorPairs.end();
       ++it )
    {
    assert( it->second.first!=NULL );
    assert( !it->second.second.IsNull() );

    const VectorImageModel::Settings& settings =
      it->second.first->GetSettings();

    //
    // Apply color-setup.
    VectorImageModel::Settings::ChannelVector channels;

    settings.GetSmartChannels( channels );

    it->second.second->SetRedIdx( channels[ RGBW_CHANNEL_RED ] + 1 );
    it->second.second->SetGreenIdx( channels[ RGBW_CHANNEL_GREEN ] + 1 );
    it->second.second->SetBlueIdx( channels[ RGBW_CHANNEL_BLUE ] + 1 );

    //
    // Apply color-dynamics.
    otb::FragmentShader::Pointer fragmentShader( it->second.second->GetShader() );

    assert(
      fragmentShader==otb::DynamicCast< otb::StandardShader >( fragmentShader )
    );

    otb::StandardShader::Pointer shader(
      otb::DynamicCast< otb::StandardShader >( fragmentShader )
    );

    assert( !shader.IsNull() );

    shader->SetMinRed( settings.GetLowIntensity( RGBW_CHANNEL_RED ) );
    shader->SetMaxRed( settings.GetHighIntensity( RGBW_CHANNEL_RED ) );

    shader->SetMinGreen( settings.GetLowIntensity( RGBW_CHANNEL_GREEN ) );
    shader->SetMaxGreen( settings.GetHighIntensity( RGBW_CHANNEL_GREEN ) );

    shader->SetMinBlue( settings.GetLowIntensity( RGBW_CHANNEL_BLUE ) );
    shader->SetMaxBlue( settings.GetHighIntensity( RGBW_CHANNEL_BLUE ) );

    shader->SetGamma( settings.GetGamma() );

    // If reference actor
    if(m_ReferenceGlImageActor.IsNotNull() && m_ReferenceGlImageActor == it->second.second)
      {
      if(m_ReferenceActorShaderMode == "LOCAL_CONTRAST")
        {
        shader->SetShaderType(otb::SHADER_LOCAL_CONTRAST);

        double localRange = 0.05 * std::max(std::max(shader->GetMaxRed()-shader->GetMinRed(),
                                                     shader->GetMaxGreen()-shader->GetMinGreen()),
                                            shader->GetMaxBlue()-shader->GetMinBlue());
        shader->SetLocalContrastRange(localRange);

        }
      else
        {
        shader->SetShaderType(otb::SHADER_STANDARD);
        }
      }
    }
}

/*******************************************************************************/
void
ImageViewRenderer
::virtual_ClearScene()
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_CleraScene()";

  //
  // Remove all actors.
  m_GlView->ClearActors();

  // Forget image-model/actors relationships.
  m_ImageModelActorPairs.clear();

  // Forget reference instances.
  m_ReferenceImageModel = NULL;
  m_ReferenceGlImageActor = otb::GlImageActor::Pointer();
}

/*******************************************************************************/
void
ImageViewRenderer
::virtual_SetImageList( const VectorImageModelList& images )
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_SetImageList(" << images << ")";

  //
  // Check that references are clear.
  assert( m_ImageModelActorPairs.empty() );
  assert( m_ReferenceImageModel==NULL );
  assert( m_ReferenceGlImageActor.IsNull() );

  //
  // Return if there is no vector-image model.
  if( images.isEmpty() )
    return;

  //
  // Insert new actors corresponding to vector-image model.
  for( VectorImageModelList::const_iterator it( images.begin() );
       it!=images.end();
       ++it )
    {
    assert( *it!=NULL );

    ImageModelActorPair pair(
      *it,
      otb::GlImageActor::New()
    );

    pair.second->Initialize( ToStdString( pair.first->GetFilename() ) );

    DatasetModel* datasetModel = pair.first->GetDatasetModel();

    ActorKey actorKey(
      m_GlView->AddActor(
        pair.second,
        pair.first==NULL
        ? std::string()
        : ToStdString( datasetModel->GetHash() )
      )
    );

    pair.second->SetVisible( true );

    m_ImageModelActorPairs.insert(
      ImageModelActorPairMap::value_type( actorKey, pair )
    );

    qDebug() << "Added image-actor:" << FromStdString( actorKey );
    }

  //
  // Remember first vector image-model as reference image-model.
  m_ReferenceImageModel = images.front();

  //
  // Remember first actor as reference actor.
  otb::GlView::StringVectorType keys( m_GlView->GetRenderingOrder() );
  assert( !keys.empty() );

  otb::GlActor::Pointer glActor( m_GlView->GetActor( keys.front() ) );
  assert( !glActor.IsNull() );

  assert( glActor==otb::DynamicCast< otb::GlImageActor >( glActor ) );

  m_ReferenceGlImageActor = otb::DynamicCast< otb::GlImageActor >( glActor );
  assert( !m_ReferenceGlImageActor.IsNull() );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/
void ImageViewRenderer::OnPhysicalCursorPositionChanged(const PointType& point,
                                       const DefaultImageType::PixelType& pixel)
{
  if(m_ReferenceGlImageActor.IsNotNull())
    {

    // Get shader of reference actor
    otb::FragmentShader::Pointer fragmentShader( m_ReferenceGlImageActor->GetShader() );

    assert(
      fragmentShader==otb::DynamicCast< otb::StandardShader >( fragmentShader )
      );

    otb::StandardShader::Pointer shader(
      otb::DynamicCast< otb::StandardShader >( fragmentShader )
      );

    assert( !shader.IsNull() );

    shader->SetShaderType(otb::SHADER_LOCAL_CONTRAST);

    if(pixel.Size()>0)
      {
      shader->SetCurrentRed(pixel[0]);
      shader->SetCurrentGreen(pixel[1]);
      shader->SetCurrentBlue(pixel[2]);
      }

    PointType p, pscreen;
    p = m_ReferenceGlImageActor->ImageToViewportTransform(point,true);

    m_GlView->GetSettings()->ViewportToScreenTransform(p[0],p[1], pscreen[0], pscreen[1]);

    pscreen[1] = m_GlView->GetSettings()->GetViewportSize()[1] - pscreen[1];

    shader->SetCenter(pscreen);
    }
}

void ImageViewRenderer::OnReferenceActorShaderModeChanged(const std::string & mode)
{
  m_ReferenceActorShaderMode = mode;
}
} // end namespace 'mvd'
<commit_msg>ENH: Changing default value of local contrast stretch<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdImageViewRenderer.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
#include <QtOpenGL>

//
// System includes (sorted by alphabetic order)
// necessary for the opengl variables and methods

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)
#include "otbStandardShader.h"

//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdDatasetModel.h"
#include "Core/mvdTypes.h"
#include "Core/mvdVectorImageModel.h"

namespace mvd
{
/*
  TRANSLATOR mvd::ImageViewRenderer

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*****************************************************************************/
ImageViewRenderer
::ImageViewRenderer( QObject* parent ) :
  AbstractImageViewRenderer( parent ),
  m_GlView( otb::GlView::New() ),
  m_ReferenceImageModel( NULL ),
  m_ReferenceGlImageActor(),
  m_ImageModelActorPairs(),
  m_ReferenceActorShaderMode("STANDARD")
{
  assert( !m_GlView.IsNull() );
}

/*****************************************************************************/
ImageViewRenderer
::~ImageViewRenderer()
{
}

/*****************************************************************************/
bool
ImageViewRenderer
::CheckGLCapabilities() const
{
  qWarning() <<
    ToStdString(
      tr( "Required OpenGL version '%1' with GLSL version '%2'." )
      .arg( otb::GlView::REQUIRED_GL_VERSION )
      .arg( otb::GlView::REQUIRED_GLSL_VERSION )
    ).c_str();

  try
    {
    qWarning() <<
      ToStdString(
        tr( "Runtime OpenGL version '%1' with GLSL version '%2'." )
        .arg( otb::GlView::GLVersion() )
        .arg( otb::GlView::GLSLVersion() )
      ).c_str();
    }
  catch( std::exception& exc )
    {
    qWarning() << ToQString( exc.what() );
    }

  try
    {
    if( otb::GlView::CheckGLCapabilities() )
      return true;

    QMessageBox::critical(
      qobject_cast< QWidget* >( parent() ),
      tr( "Monteverdi2 - Critical error!" ),
      tr( "Current OpenGL version is '%1' supporting GLSL version '%2'.\nRequired OpenGL version is '%3' with Shading-Laguage version '%4'.\nPlease upgrade your graphics driver and hardware for the application to run properly on this platform.\nUsing the application on this platform may lead to unknown behaviour. Would you still like to continue using the application?" )
      .arg( otb::GlView::GLVersion() )
      .arg( otb::GlView::GLSLVersion() )
      .arg( otb::GlView::REQUIRED_GL_VERSION )
      .arg( otb::GlView::REQUIRED_GLSL_VERSION )
    );
    }
  catch( std::exception& exc )
    {
    QMessageBox::critical(
      qobject_cast< QWidget* >( parent() ),
      tr( "Monteverdi2 - Critical error!"),
      ToQString( exc.what() )
    );
    }

  return false;
}

/*****************************************************************************/
AbstractImageViewRenderer::RenderingContext*
ImageViewRenderer
::NewRenderingContext() const
{
  RenderingContext* context = new ImageViewRenderer::RenderingContext();

#if USE_VIEW_SETTINGS_SIDE_EFFECT
#else
  assert( !m_GlView.IsNull() );

  //
  // Share otb::GlViewRendering settings with manipulator using
  // RenderingContext. Manipulator can then setup otb::ViewSettings
  // directly by side-effect.
  context->m_ViewSettings = m_GlView->GetSettings();
#endif

  return context;
}

/*****************************************************************************/
const AbstractImageModel*
ImageViewRenderer
::GetReferenceImageModel() const
{
  return m_ReferenceImageModel;
}

/*****************************************************************************/
AbstractImageModel*
ImageViewRenderer
::GetReferenceImageModel()
{
  return m_ReferenceImageModel;
}

/*****************************************************************************/
void
ImageViewRenderer
::GetReferenceExtent( PointType& origin, PointType& extent  ) const
{
  assert( !m_ReferenceGlImageActor.IsNull() );

  m_ReferenceGlImageActor->GetExtent(
    origin[ 0 ], origin[ 1 ],
    extent[ 0 ], extent[ 1 ]
  );
}

/*****************************************************************************/
void
ImageViewRenderer
::InitializeGL()
{
  assert( !m_GlView.IsNull() );

  //
  // WARNING: This call to otb::GlView::Initialize() allocates a new
  // otb::ViewSettings() instance. So, the shared pointer between
  // renderer and manipulator may be unshated depending on order of
  // calls.
  //
  m_GlView->Initialize( 0, 0 );
}

/*****************************************************************************/
void
ImageViewRenderer
::ResizeGL( int width, int height )
{
  // qDebug() << this << "::ResizeGL(" << width << "," << height << ")";

  /*
  // Should be done here and not in OTB-Ice render routine.
  glViewport(
    0,
    0,
    static_cast< GLint >( width ),
    static_cast< GLint >( height )
  );
  */

  assert( !m_GlView.IsNull() );

  // qDebug() << m_GlView.GetPointer();

  m_GlView->Resize( width, height );

  /*
  glViewport(
    0, 0,
    static_cast< GLint >( width ), static_cast< GLint >( height )
  );

  glMatrixMode( GL_MODELVIEW );
  glLoadIdentity();

  glMatrixMode( GL_PROJECTION );
  glLoadIdentity();
  glOrtho(
    0, static_cast< GLint >( width ),
    0, static_cast< GLint >( height ),
    0, 1
  );
  */
}

/*****************************************************************************/
void
ImageViewRenderer
::PaintGL( const AbstractImageViewRenderer::RenderingContext* c )
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::PaintGL(" << c << ")";

  // qDebug() << m_GlView.GetPointer();

  /*
  //
  // Get appropriate rendering-context.
  assert( c==dynamic_cast< RenderingContext* >( c ) );
  RenderingContext* context = dynamic_cast< RenderingContext* >( c );
  assert( context!=NULL );

  //
  // Set view settings.
  m_GlView->SetSettings( context->m_ViewSettings );
  */

  //
  // Apply VectorImageModel::Settings to otb::GlImageActor.
  UpdateActors( c );

  //
  // Pre-render scene.
  m_GlView->BeforeRendering();
  {
  //
  // Render scene.
  switch( c->m_RenderMode )
    {
    case RenderingContext::RENDER_MODE_LIGHT:
      m_GlView->LightRender();
      break;

    case RenderingContext::RENDER_MODE_FULL:
      m_GlView->HeavyRender();
      break;
    }
  }
  //
  // Post-render scene.
  m_GlView->AfterRendering();
}

/*****************************************************************************/
bool
ImageViewRenderer
::Pick( const PointType& in,
        PointType& out,
        DefaultImageType::PixelType& pixel )
{
  /*
  qDebug()
    << this << "::Pick("
    << in[ 0 ] << "," << in[ 1 ]
    << ")";
  */

  if( m_ReferenceGlImageActor.IsNull() )
    return false;

  //
  // Compute output/physical point.
  out = m_ReferenceGlImageActor->ViewportToImageTransform( in, true );

  //
  // Read pixel value.
  return m_ReferenceGlImageActor->GetPixelFromViewport( in, pixel );
}

/*****************************************************************************/
bool
ImageViewRenderer
::Transform( PointType& point, const IndexType& index, bool isPhysical ) const
{
  if( m_ReferenceGlImageActor.IsNull() )
    return false;

  point[ 0 ] = static_cast< double >( index[ 0 ] );
  point[ 1 ] = static_cast< double >( index[ 1 ] );

  point = m_ReferenceGlImageActor->ImageToViewportTransform( point, isPhysical );

  return true;
}

/*****************************************************************************/
void
ImageViewRenderer
::UpdateActors( const AbstractImageViewRenderer::RenderingContext* )
{
  UpdateImageActors();
}

/*****************************************************************************/
void
ImageViewRenderer
::UpdateImageActors()
{
  for( ImageModelActorPairMap::const_iterator it(m_ImageModelActorPairs.begin());
       it!=m_ImageModelActorPairs.end();
       ++it )
    {
    assert( it->second.first!=NULL );
    assert( !it->second.second.IsNull() );

    const VectorImageModel::Settings& settings =
      it->second.first->GetSettings();

    //
    // Apply color-setup.
    VectorImageModel::Settings::ChannelVector channels;

    settings.GetSmartChannels( channels );

    it->second.second->SetRedIdx( channels[ RGBW_CHANNEL_RED ] + 1 );
    it->second.second->SetGreenIdx( channels[ RGBW_CHANNEL_GREEN ] + 1 );
    it->second.second->SetBlueIdx( channels[ RGBW_CHANNEL_BLUE ] + 1 );

    //
    // Apply color-dynamics.
    otb::FragmentShader::Pointer fragmentShader( it->second.second->GetShader() );

    assert(
      fragmentShader==otb::DynamicCast< otb::StandardShader >( fragmentShader )
    );

    otb::StandardShader::Pointer shader(
      otb::DynamicCast< otb::StandardShader >( fragmentShader )
    );

    assert( !shader.IsNull() );

    shader->SetMinRed( settings.GetLowIntensity( RGBW_CHANNEL_RED ) );
    shader->SetMaxRed( settings.GetHighIntensity( RGBW_CHANNEL_RED ) );

    shader->SetMinGreen( settings.GetLowIntensity( RGBW_CHANNEL_GREEN ) );
    shader->SetMaxGreen( settings.GetHighIntensity( RGBW_CHANNEL_GREEN ) );

    shader->SetMinBlue( settings.GetLowIntensity( RGBW_CHANNEL_BLUE ) );
    shader->SetMaxBlue( settings.GetHighIntensity( RGBW_CHANNEL_BLUE ) );

    shader->SetGamma( settings.GetGamma() );

    // If reference actor
    if(m_ReferenceGlImageActor.IsNotNull() && m_ReferenceGlImageActor == it->second.second)
      {
      if(m_ReferenceActorShaderMode == "LOCAL_CONTRAST")
        {
        shader->SetShaderType(otb::SHADER_LOCAL_CONTRAST);

        double localRange = 0.1 * std::max(std::max(shader->GetMaxRed()-shader->GetMinRed(),
                                                     shader->GetMaxGreen()-shader->GetMinGreen()),
                                            shader->GetMaxBlue()-shader->GetMinBlue());
        shader->SetLocalContrastRange(localRange);

        }
      else
        {
        shader->SetShaderType(otb::SHADER_STANDARD);
        }
      }
    }
}

/*******************************************************************************/
void
ImageViewRenderer
::virtual_ClearScene()
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_CleraScene()";

  //
  // Remove all actors.
  m_GlView->ClearActors();

  // Forget image-model/actors relationships.
  m_ImageModelActorPairs.clear();

  // Forget reference instances.
  m_ReferenceImageModel = NULL;
  m_ReferenceGlImageActor = otb::GlImageActor::Pointer();
}

/*******************************************************************************/
void
ImageViewRenderer
::virtual_SetImageList( const VectorImageModelList& images )
{
  assert( !m_GlView.IsNull() );

  // qDebug() << this << "::virtual_SetImageList(" << images << ")";

  //
  // Check that references are clear.
  assert( m_ImageModelActorPairs.empty() );
  assert( m_ReferenceImageModel==NULL );
  assert( m_ReferenceGlImageActor.IsNull() );

  //
  // Return if there is no vector-image model.
  if( images.isEmpty() )
    return;

  //
  // Insert new actors corresponding to vector-image model.
  for( VectorImageModelList::const_iterator it( images.begin() );
       it!=images.end();
       ++it )
    {
    assert( *it!=NULL );

    ImageModelActorPair pair(
      *it,
      otb::GlImageActor::New()
    );

    pair.second->Initialize( ToStdString( pair.first->GetFilename() ) );

    DatasetModel* datasetModel = pair.first->GetDatasetModel();

    ActorKey actorKey(
      m_GlView->AddActor(
        pair.second,
        pair.first==NULL
        ? std::string()
        : ToStdString( datasetModel->GetHash() )
      )
    );

    pair.second->SetVisible( true );

    m_ImageModelActorPairs.insert(
      ImageModelActorPairMap::value_type( actorKey, pair )
    );

    qDebug() << "Added image-actor:" << FromStdString( actorKey );
    }

  //
  // Remember first vector image-model as reference image-model.
  m_ReferenceImageModel = images.front();

  //
  // Remember first actor as reference actor.
  otb::GlView::StringVectorType keys( m_GlView->GetRenderingOrder() );
  assert( !keys.empty() );

  otb::GlActor::Pointer glActor( m_GlView->GetActor( keys.front() ) );
  assert( !glActor.IsNull() );

  assert( glActor==otb::DynamicCast< otb::GlImageActor >( glActor ) );

  m_ReferenceGlImageActor = otb::DynamicCast< otb::GlImageActor >( glActor );
  assert( !m_ReferenceGlImageActor.IsNull() );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/
void ImageViewRenderer::OnPhysicalCursorPositionChanged(const PointType& point,
                                       const DefaultImageType::PixelType& pixel)
{
  if(m_ReferenceGlImageActor.IsNotNull())
    {

    // Get shader of reference actor
    otb::FragmentShader::Pointer fragmentShader( m_ReferenceGlImageActor->GetShader() );

    assert(
      fragmentShader==otb::DynamicCast< otb::StandardShader >( fragmentShader )
      );

    otb::StandardShader::Pointer shader(
      otb::DynamicCast< otb::StandardShader >( fragmentShader )
      );

    assert( !shader.IsNull() );

    shader->SetShaderType(otb::SHADER_LOCAL_CONTRAST);

    if(pixel.Size()>0)
      {
      shader->SetCurrentRed(pixel[0]);
      shader->SetCurrentGreen(pixel[1]);
      shader->SetCurrentBlue(pixel[2]);
      }

    PointType p, pscreen;
    p = m_ReferenceGlImageActor->ImageToViewportTransform(point,true);

    m_GlView->GetSettings()->ViewportToScreenTransform(p[0],p[1], pscreen[0], pscreen[1]);

    pscreen[1] = m_GlView->GetSettings()->GetViewportSize()[1] - pscreen[1];

    shader->SetCenter(pscreen);
    }
}

void ImageViewRenderer::OnReferenceActorShaderModeChanged(const std::string & mode)
{
  m_ReferenceActorShaderMode = mode;
}
} // end namespace 'mvd'
<|endoftext|>


<commit_before>#include <lms/framework.h>
#include <lms/executionmanager.h>
#include <pugixml.hpp>
#include <fstream>
#include <csignal>
#include <map>
#include <cstdlib>
#include "lms/extra/backtrace_formatter.h"
#include "lms/logging/log_level.h"
#include "lms/extra/time.h"
#include "lms/type/module_config.h"
#include "lms/extra/string.h"

namespace lms{

std::string Framework::externalDirectory = EXTERNAL_DIR;
std::string Framework::configsDirectory = CONFIGS_DIR;

Framework::Framework(const ArgumentHandler &arguments) :
    logger("FRAMEWORK", &rootLogger), argumentHandler(arguments), executionManager(rootLogger),
    clockEnabled(false), clock(rootLogger), monitorEnabled(false) {

    rootLogger.filter(std::unique_ptr<logging::LoggingFilter>(new logging::PrefixAndLevelFilter(
        arguments.argLoggingMinLevel(), arguments.argLoggingPrefixes())));

    SignalHandler::getInstance()
            .addListener(SIGINT, this)
            .addListener(SIGSEGV, this);

    logger.info() << "RunLevel " <<  arguments.argRunLevel();

    //parse framework config
    if(arguments.argRunLevel() >= RunLevel::CONFIG) {
        parseConfig(LoadConfigFlag::LOAD_EVERYTHING);
    }

    if(arguments.argRunLevel() >= RunLevel::ENABLE) {
        // enable modules after they were made available
        logger.info() << "Start enabling modules";
        for(ModuleToLoad mod : tempModulesToLoadList) {
            executionManager.enableModule(mod.name, mod.logLevel);
        }

        if(arguments.argRunLevel() == RunLevel::ENABLE) {
            executionManager.getDataManager().printMapping();
            executionManager.validate();
            executionManager.printCycleList();
        }
    }

    if(arguments.argRunLevel() >= RunLevel::CYCLE) {
        //Execution
        running = true;

        while(running) {
            if(clockEnabled) {
                clock.beforeLoopIteration();
            }

            executionManager.loop();

            if(clockEnabled) {
                clock.afterLoopIteration();
            }

            if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
                    && monitor.hasChangedFiles()) {
                monitor.unwatchAll();
                parseConfig(LoadConfigFlag::ONLY_MODULE_CONFIG);
            }
        }
    }
}
/*
 * TODO suffix for config
 */
void Framework::parseConfig(LoadConfigFlag flag){

    logger.debug("parseConfig") << "EXTERNAL: " << externalDirectory
                                << std::endl << "CONFIGS: " << configsDirectory;

    std::string configPath = configsDirectory + "/";
    if(argumentHandler.argLoadConfiguration().empty()) {
        configPath += "framework_conf.xml";
    } else {
        configPath += argumentHandler.argLoadConfiguration() + ".xml";
    }

    parseFile(configPath, flag);
}

void Framework::parseFile(const std::string &file, LoadConfigFlag flag) {
    logger.debug("parseFile") << "Reading XML file: " << file;
    if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
            && !monitor.watch(file)) {
        logger.error("parseFile") << "Could not monitor " << file;
    }

    std::ifstream ifs;
    ifs.open (file, std::ifstream::in);
    if(ifs.is_open()){
        pugi::xml_document doc;
        pugi::xml_parse_result result = doc.load(ifs);
        if (result){
            pugi::xml_node rootNode = doc.child("framework");

            if(flag != LoadConfigFlag::ONLY_MODULE_CONFIG) {
                // parse <execution> tag (or deprecated <executionManager>)
                parseExecution(rootNode);

                // parse <moduleToEnable> tag (or deprecated <modulesToLoad>)
                parseModulesToEnable(rootNode);
            }

            // parse all <module> tags
            parseModules(rootNode, file, flag);

            // parse all <include> tags
            parseIncludes(rootNode, file, flag);
        } else {
            logger.error() << "Failed to parse " << file << " as XML";
        }
    } else {
        logger.error() << "Failed to open XML file " << file;
    }
}

void Framework::parseExecution(pugi::xml_node rootNode) {
    pugi::xml_node execNode = rootNode.child("execution");

    if(!execNode) {
        execNode = rootNode.child("executionManager");

        if(execNode) {
            logger.warn("parseExecution")
                << "Found deprecated tag <executionManager>, use <execution> instead";
        } else {
            // do not parse anything
            return;
        }
    }

    pugi::xml_node threadPoolNode = execNode.child("maxThreadCount");

    if(threadPoolNode) {
        int maxThreads = atoi(threadPoolNode.child_value());
        executionManager.setMaxThreads(maxThreads);
        logger.info("parseExecution") << "Thread pool size: " << maxThreads;
    }

    pugi::xml_node clockNode = execNode.child("clock");

    if(clockNode) {
        std::string clockUnit;
        std::int64_t clockValue = atoll(clockNode.child_value());

        pugi::xml_attribute enabledAttr = clockNode.attribute("enable");
        pugi::xml_attribute unitAttr = clockNode.attribute("unit");

        if(enabledAttr) {
            clockEnabled = enabledAttr.as_bool();
        } else {
            // if no enabled attribute is given then the clock is considered
            // to be enabled
            clockEnabled = true;
        }

        if(unitAttr) {
            clockUnit = unitAttr.value();
        } else {
            logger.warn("parseExecution")
                << "Missing attribute unit=\"hz/ms/us\" for tag <clock>";
            clockEnabled = false;
        }

        if(clockEnabled) {
            if(clockUnit == "hz") {
                clock.cycleTime(extra::PrecisionTime::fromMicros(1000000 / clockValue));
            } else if(clockUnit == "ms") {
                clock.cycleTime(extra::PrecisionTime::fromMillis(clockValue));
            } else if(clockUnit == "us") {
                clock.cycleTime(extra::PrecisionTime::fromMicros(clockValue));
            } else {
                logger.error("parseConfig")
                    << "Invalid value for attribute unit in <clock>: "
                    << clockUnit;
                clockEnabled = false;
            }
        }
    }

    if(clockEnabled) {
        logger.info("parseConfig") << "Enabled clock with " << clock.cycleTime();
    } else {
        logger.info("parseConfig") << "Disabled clock";
    }

    pugi::xml_node configMonitorNode = execNode.child("configMonitor");

    if(configMonitorNode) {
        std::string configMonitorText = configMonitorNode.child_value();

        if(configMonitorText == "true") {
            monitorEnabled = true;
        } else if(configMonitorText == "false") {
            monitorEnabled = false;
        } else {
            logger.warn("parseConfig") << "Invalid value for <configMonitor>";
        }
    }

    if(monitorEnabled) {
        logger.info("parseConfig") << "Enabled config monitor";
    } else {
        logger.info("parseConfig") << "Disable config monitor";
    }
}

void Framework::parseModulesToEnable(pugi::xml_node rootNode) {
    pugi::xml_node enableNode = rootNode.child("modulesToEnable");

    if(! enableNode) {
        enableNode = rootNode.child("modulesToLoad");

        if(enableNode) {
            logger.warn("parseModulesToEnable")
                << "Found deprecated tag <modulesToLoad>, use <modulesToEnable> instead";
        } else {
            // do not parse anything
            return;
        }
    }

    lms::logging::LogLevel defaultModuleLevel = lms::logging::SMALLEST_LEVEL;

    // get attribute "logLevel" of node <modulesToLoad>
    // its value will be the default for logLevel of <module>
    pugi::xml_attribute globalLogLevelAttr = enableNode.attribute("logLevel");
    if(globalLogLevelAttr) {
        defaultModuleLevel = lms::logging::levelFromName(globalLogLevelAttr.value());
    }

    for (pugi::xml_node moduleNode : enableNode.children("module")){
        //parse module content
        ModuleToLoad mod;
        mod.name = moduleNode.child_value();

        // get the attribute "logLevel"
        pugi::xml_attribute logLevelAttr = moduleNode.attribute("logLevel");
        if(logLevelAttr) {
            mod.logLevel = lms::logging::levelFromName(logLevelAttr.value());
        } else {
            mod.logLevel = defaultModuleLevel;
        }

        tempModulesToLoadList.push_back(mod);
    }
}

void Framework::parseModules(pugi::xml_node rootNode,
                             const std::string &currentFile,
                             LoadConfigFlag flag) {
    // parse all <module> nodes
    for (pugi::xml_node moduleNode : rootNode.children("module")) {

        Loader::module_entry module;
        std::map<std::string, type::ModuleConfig> configMap;

        module.name = moduleNode.child("name").child_value();
        logger.info("parseModules") << "Found def for module " << module.name;

        pugi::xml_node realNameNode = moduleNode.child("realName");

        if(realNameNode) {
            module.libpath = externalDirectory + "/modules/" +
                    realNameNode.child_value() + "/" +
                    Loader::getModulePath(realNameNode.child_value());
        } else {
            pugi::xml_node libpathNode = moduleNode.child("libpath");
            pugi::xml_node libnameNode = moduleNode.child("libname");

            std::string libname;
            if(libnameNode) {
                libname = Loader::getModulePath(libnameNode.child_value());
            } else {
                libname = Loader::getModulePath(module.name);
            }

            if(libpathNode) {
                // TODO better relative path here
                module.libpath = externalDirectory + "/modules/" +
                        libpathNode.child_value() + "/" + libname;
            } else {
                module.libpath = externalDirectory + "/modules/" + module.name
                        + "/" + libname;
            }
        }

        pugi::xml_node writePrioNode = moduleNode.child("writePriority");

        if(writePrioNode) {
            module.writePriority = atoi(writePrioNode.child_value());
        } else {
            module.writePriority = 0;
        }

        // parse all channel mappings
        for(pugi::xml_node mappingNode : moduleNode.children("channelMapping")) {
            pugi::xml_attribute fromAttr = mappingNode.attribute("from");
            pugi::xml_attribute toAttr = mappingNode.attribute("to");

            if(fromAttr && toAttr) {
                module.channelMapping[fromAttr.value()] = toAttr.value();
            } else {
                logger.warn("parseModules")
                    << "Tag <channelMapping> requires from and to attributes";
            }
        }

        // parse all config
        for(pugi::xml_node configNode : moduleNode.children("config")) {
            pugi::xml_attribute srcAttr = configNode.attribute("src");
            pugi::xml_attribute nameAttr = configNode.attribute("name");

            std::string name = "default";
            if(nameAttr) {
                name = nameAttr.value();
            }

            if(srcAttr) {
                std::string lconfPath = srcAttr.value();

                if(extra::isAbsolute(lconfPath)) {
                    lconfPath = configsDirectory + lconfPath;
                } else {
                    lconfPath = extra::dirname(currentFile) + "/" + lconfPath;
                }

                bool loadResult = configMap[name].loadFromFile(lconfPath);
                if(!loadResult) {
                    logger.error("parseModules") << "Tried to load "
                        << srcAttr.value() << " for " << module.name << " but failed";

                } else {
                    logger.info("parseModules") << "Loaded " << lconfPath;
                    if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
                            && !monitor.watch(lconfPath)) {
                        logger.error("parseModules") << "Failed to monitor "
                                                     << lconfPath;
                    }
                }
            } else {
                // if there was no src attribut then parse the tag's content
                for (pugi::xml_node configPropNode: configNode.children()) {
                    logger.debug("parseModules") << configPropNode.name();
                    configMap[name].set(configPropNode.name(),
                                     std::string(configPropNode.child_value()));
                }
            }
        }

        for(std::pair<std::string, type::ModuleConfig> pair : configMap) {
            executionManager.getDataManager()
                .setChannel<type::ModuleConfig>(
                "CONFIG_" + module.name + "_" + pair.first, pair.second);
        }

        if(flag != LoadConfigFlag::ONLY_MODULE_CONFIG) {
            executionManager.addAvailableModule(module);
        }
    }
}

void Framework::parseIncludes(pugi::xml_node rootNode,
                              const std::string &currentFile,
                              LoadConfigFlag flag) {
    for(pugi::xml_node includeNode : rootNode.children("include")) {
        pugi::xml_attribute srcAttr = includeNode.attribute("src");

        if(srcAttr) {
            logger.info("parseIncludes") << "Found include " << srcAttr.value();

            std::string includePath = srcAttr.value();
            if(extra::isAbsolute(includePath)) {
                // if absolute then start from configs dir
                includePath = configsDirectory + includePath;
            } else {
                // otherwise go from current file's directory
                includePath = extra::dirname(currentFile) + "/" + includePath;
            }
            parseFile(includePath, flag);
        } else {
            logger.error("Include tag has no src attribute");
        }
    }
}

Framework::~Framework() {
    logger.info() << "Removing Signal listeners";
    SignalHandler::getInstance()
            .removeListener(SIGINT, this)
            .removeListener(SIGSEGV, this);
}

void Framework::signal(int s) {
    switch (s) {
    case SIGINT:
        running = false;

        logger.warn() << "Terminating after next Cycle. Press CTRL+C again to terminate immediately";

        SignalHandler::getInstance().removeListener(SIGINT, this);

        break;
    case SIGSEGV:
        //Segmentation Fault - try to identify what went wrong;
        logger.error()
                << "######################################################" << std::endl
                << "                   Segfault Found                     " << std::endl
                << "######################################################";

        //In Case of Segfault while recovering - shutdown.
        SignalHandler::getInstance().removeListener(SIGSEGV, this);

        extra::printStacktrace();

        exit(EXIT_FAILURE);

        break;
    }
}
}
<commit_msg>Fix config parsing: clock enabled instead of enable<commit_after>#include <lms/framework.h>
#include <lms/executionmanager.h>
#include <pugixml.hpp>
#include <fstream>
#include <csignal>
#include <map>
#include <cstdlib>
#include "lms/extra/backtrace_formatter.h"
#include "lms/logging/log_level.h"
#include "lms/extra/time.h"
#include "lms/type/module_config.h"
#include "lms/extra/string.h"

namespace lms{

std::string Framework::externalDirectory = EXTERNAL_DIR;
std::string Framework::configsDirectory = CONFIGS_DIR;

Framework::Framework(const ArgumentHandler &arguments) :
    logger("FRAMEWORK", &rootLogger), argumentHandler(arguments), executionManager(rootLogger),
    clockEnabled(false), clock(rootLogger), monitorEnabled(false) {

    rootLogger.filter(std::unique_ptr<logging::LoggingFilter>(new logging::PrefixAndLevelFilter(
        arguments.argLoggingMinLevel(), arguments.argLoggingPrefixes())));

    SignalHandler::getInstance()
            .addListener(SIGINT, this)
            .addListener(SIGSEGV, this);

    logger.info() << "RunLevel " <<  arguments.argRunLevel();

    //parse framework config
    if(arguments.argRunLevel() >= RunLevel::CONFIG) {
        parseConfig(LoadConfigFlag::LOAD_EVERYTHING);
    }

    if(arguments.argRunLevel() >= RunLevel::ENABLE) {
        // enable modules after they were made available
        logger.info() << "Start enabling modules";
        for(ModuleToLoad mod : tempModulesToLoadList) {
            executionManager.enableModule(mod.name, mod.logLevel);
        }

        if(arguments.argRunLevel() == RunLevel::ENABLE) {
            executionManager.getDataManager().printMapping();
            executionManager.validate();
            executionManager.printCycleList();
        }
    }

    if(arguments.argRunLevel() >= RunLevel::CYCLE) {
        //Execution
        running = true;

        while(running) {
            if(clockEnabled) {
                clock.beforeLoopIteration();
            }

            executionManager.loop();

            if(clockEnabled) {
                clock.afterLoopIteration();
            }

            if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
                    && monitor.hasChangedFiles()) {
                monitor.unwatchAll();
                parseConfig(LoadConfigFlag::ONLY_MODULE_CONFIG);
            }
        }
    }
}
/*
 * TODO suffix for config
 */
void Framework::parseConfig(LoadConfigFlag flag){

    logger.debug("parseConfig") << "EXTERNAL: " << externalDirectory
                                << std::endl << "CONFIGS: " << configsDirectory;

    std::string configPath = configsDirectory + "/";
    if(argumentHandler.argLoadConfiguration().empty()) {
        configPath += "framework_conf.xml";
    } else {
        configPath += argumentHandler.argLoadConfiguration() + ".xml";
    }

    parseFile(configPath, flag);
}

void Framework::parseFile(const std::string &file, LoadConfigFlag flag) {
    logger.debug("parseFile") << "Reading XML file: " << file;
    if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
            && !monitor.watch(file)) {
        logger.error("parseFile") << "Could not monitor " << file;
    }

    std::ifstream ifs;
    ifs.open (file, std::ifstream::in);
    if(ifs.is_open()){
        pugi::xml_document doc;
        pugi::xml_parse_result result = doc.load(ifs);
        if (result){
            pugi::xml_node rootNode = doc.child("framework");

            if(flag != LoadConfigFlag::ONLY_MODULE_CONFIG) {
                // parse <execution> tag (or deprecated <executionManager>)
                parseExecution(rootNode);

                // parse <moduleToEnable> tag (or deprecated <modulesToLoad>)
                parseModulesToEnable(rootNode);
            }

            // parse all <module> tags
            parseModules(rootNode, file, flag);

            // parse all <include> tags
            parseIncludes(rootNode, file, flag);
        } else {
            logger.error() << "Failed to parse " << file << " as XML";
        }
    } else {
        logger.error() << "Failed to open XML file " << file;
    }
}

void Framework::parseExecution(pugi::xml_node rootNode) {
    pugi::xml_node execNode = rootNode.child("execution");

    if(!execNode) {
        execNode = rootNode.child("executionManager");

        if(execNode) {
            logger.warn("parseExecution")
                << "Found deprecated tag <executionManager>, use <execution> instead";
        } else {
            // do not parse anything
            return;
        }
    }

    pugi::xml_node threadPoolNode = execNode.child("maxThreadCount");

    if(threadPoolNode) {
        int maxThreads = atoi(threadPoolNode.child_value());
        executionManager.setMaxThreads(maxThreads);
        logger.info("parseExecution") << "Thread pool size: " << maxThreads;
    }

    pugi::xml_node clockNode = execNode.child("clock");

    if(clockNode) {
        std::string clockUnit;
        std::int64_t clockValue = atoll(clockNode.child_value());

        pugi::xml_attribute enabledAttr = clockNode.attribute("enabled");
        pugi::xml_attribute unitAttr = clockNode.attribute("unit");

        if(enabledAttr) {
            clockEnabled = enabledAttr.as_bool();
        } else {
            // if no enabled attribute is given then the clock is considered
            // to be disabled
            clockEnabled = false;
        }

        if(unitAttr) {
            clockUnit = unitAttr.value();
        } else {
            logger.warn("parseExecution")
                << "Missing attribute unit=\"hz/ms/us\" for tag <clock>";
            clockEnabled = false;
        }

        if(clockEnabled) {
            if(clockUnit == "hz") {
                clock.cycleTime(extra::PrecisionTime::fromMicros(1000000 / clockValue));
            } else if(clockUnit == "ms") {
                clock.cycleTime(extra::PrecisionTime::fromMillis(clockValue));
            } else if(clockUnit == "us") {
                clock.cycleTime(extra::PrecisionTime::fromMicros(clockValue));
            } else {
                logger.error("parseConfig")
                    << "Invalid value for attribute unit in <clock>: "
                    << clockUnit;
                clockEnabled = false;
            }
        }
    }

    if(clockEnabled) {
        logger.info("parseConfig") << "Enabled clock with " << clock.cycleTime();
    } else {
        logger.info("parseConfig") << "Disabled clock";
    }

    pugi::xml_node configMonitorNode = execNode.child("configMonitor");

    if(configMonitorNode) {
        std::string configMonitorText = configMonitorNode.child_value();

        if(configMonitorText == "true") {
            monitorEnabled = true;
        } else if(configMonitorText == "false") {
            monitorEnabled = false;
        } else {
            logger.warn("parseConfig") << "Invalid value for <configMonitor>";
        }
    }

    if(monitorEnabled) {
        logger.info("parseConfig") << "Enabled config monitor";
    } else {
        logger.info("parseConfig") << "Disable config monitor";
    }
}

void Framework::parseModulesToEnable(pugi::xml_node rootNode) {
    pugi::xml_node enableNode = rootNode.child("modulesToEnable");

    if(! enableNode) {
        enableNode = rootNode.child("modulesToLoad");

        if(enableNode) {
            logger.warn("parseModulesToEnable")
                << "Found deprecated tag <modulesToLoad>, use <modulesToEnable> instead";
        } else {
            // do not parse anything
            return;
        }
    }

    lms::logging::LogLevel defaultModuleLevel = lms::logging::SMALLEST_LEVEL;

    // get attribute "logLevel" of node <modulesToLoad>
    // its value will be the default for logLevel of <module>
    pugi::xml_attribute globalLogLevelAttr = enableNode.attribute("logLevel");
    if(globalLogLevelAttr) {
        defaultModuleLevel = lms::logging::levelFromName(globalLogLevelAttr.value());
    }

    for (pugi::xml_node moduleNode : enableNode.children("module")){
        //parse module content
        ModuleToLoad mod;
        mod.name = moduleNode.child_value();

        // get the attribute "logLevel"
        pugi::xml_attribute logLevelAttr = moduleNode.attribute("logLevel");
        if(logLevelAttr) {
            mod.logLevel = lms::logging::levelFromName(logLevelAttr.value());
        } else {
            mod.logLevel = defaultModuleLevel;
        }

        tempModulesToLoadList.push_back(mod);
    }
}

void Framework::parseModules(pugi::xml_node rootNode,
                             const std::string &currentFile,
                             LoadConfigFlag flag) {
    // parse all <module> nodes
    for (pugi::xml_node moduleNode : rootNode.children("module")) {

        Loader::module_entry module;
        std::map<std::string, type::ModuleConfig> configMap;

        module.name = moduleNode.child("name").child_value();
        logger.info("parseModules") << "Found def for module " << module.name;

        pugi::xml_node realNameNode = moduleNode.child("realName");

        if(realNameNode) {
            module.libpath = externalDirectory + "/modules/" +
                    realNameNode.child_value() + "/" +
                    Loader::getModulePath(realNameNode.child_value());
        } else {
            pugi::xml_node libpathNode = moduleNode.child("libpath");
            pugi::xml_node libnameNode = moduleNode.child("libname");

            std::string libname;
            if(libnameNode) {
                libname = Loader::getModulePath(libnameNode.child_value());
            } else {
                libname = Loader::getModulePath(module.name);
            }

            if(libpathNode) {
                // TODO better relative path here
                module.libpath = externalDirectory + "/modules/" +
                        libpathNode.child_value() + "/" + libname;
            } else {
                module.libpath = externalDirectory + "/modules/" + module.name
                        + "/" + libname;
            }
        }

        pugi::xml_node writePrioNode = moduleNode.child("writePriority");

        if(writePrioNode) {
            module.writePriority = atoi(writePrioNode.child_value());
        } else {
            module.writePriority = 0;
        }

        // parse all channel mappings
        for(pugi::xml_node mappingNode : moduleNode.children("channelMapping")) {
            pugi::xml_attribute fromAttr = mappingNode.attribute("from");
            pugi::xml_attribute toAttr = mappingNode.attribute("to");

            if(fromAttr && toAttr) {
                module.channelMapping[fromAttr.value()] = toAttr.value();
            } else {
                logger.warn("parseModules")
                    << "Tag <channelMapping> requires from and to attributes";
            }
        }

        // parse all config
        for(pugi::xml_node configNode : moduleNode.children("config")) {
            pugi::xml_attribute srcAttr = configNode.attribute("src");
            pugi::xml_attribute nameAttr = configNode.attribute("name");

            std::string name = "default";
            if(nameAttr) {
                name = nameAttr.value();
            }

            if(srcAttr) {
                std::string lconfPath = srcAttr.value();

                if(extra::isAbsolute(lconfPath)) {
                    lconfPath = configsDirectory + lconfPath;
                } else {
                    lconfPath = extra::dirname(currentFile) + "/" + lconfPath;
                }

                bool loadResult = configMap[name].loadFromFile(lconfPath);
                if(!loadResult) {
                    logger.error("parseModules") << "Tried to load "
                        << srcAttr.value() << " for " << module.name << " but failed";

                } else {
                    logger.info("parseModules") << "Loaded " << lconfPath;
                    if(lms::extra::FILE_MONITOR_SUPPORTED && monitorEnabled
                            && !monitor.watch(lconfPath)) {
                        logger.error("parseModules") << "Failed to monitor "
                                                     << lconfPath;
                    }
                }
            } else {
                // if there was no src attribut then parse the tag's content
                for (pugi::xml_node configPropNode: configNode.children()) {
                    logger.debug("parseModules") << configPropNode.name();
                    configMap[name].set(configPropNode.name(),
                                     std::string(configPropNode.child_value()));
                }
            }
        }

        for(std::pair<std::string, type::ModuleConfig> pair : configMap) {
            executionManager.getDataManager()
                .setChannel<type::ModuleConfig>(
                "CONFIG_" + module.name + "_" + pair.first, pair.second);
        }

        if(flag != LoadConfigFlag::ONLY_MODULE_CONFIG) {
            executionManager.addAvailableModule(module);
        }
    }
}

void Framework::parseIncludes(pugi::xml_node rootNode,
                              const std::string &currentFile,
                              LoadConfigFlag flag) {
    for(pugi::xml_node includeNode : rootNode.children("include")) {
        pugi::xml_attribute srcAttr = includeNode.attribute("src");

        if(srcAttr) {
            logger.info("parseIncludes") << "Found include " << srcAttr.value();

            std::string includePath = srcAttr.value();
            if(extra::isAbsolute(includePath)) {
                // if absolute then start from configs dir
                includePath = configsDirectory + includePath;
            } else {
                // otherwise go from current file's directory
                includePath = extra::dirname(currentFile) + "/" + includePath;
            }
            parseFile(includePath, flag);
        } else {
            logger.error("Include tag has no src attribute");
        }
    }
}

Framework::~Framework() {
    logger.info() << "Removing Signal listeners";
    SignalHandler::getInstance()
            .removeListener(SIGINT, this)
            .removeListener(SIGSEGV, this);
}

void Framework::signal(int s) {
    switch (s) {
    case SIGINT:
        running = false;

        logger.warn() << "Terminating after next Cycle. Press CTRL+C again to terminate immediately";

        SignalHandler::getInstance().removeListener(SIGINT, this);

        break;
    case SIGSEGV:
        //Segmentation Fault - try to identify what went wrong;
        logger.error()
                << "######################################################" << std::endl
                << "                   Segfault Found                     " << std::endl
                << "######################################################";

        //In Case of Segfault while recovering - shutdown.
        SignalHandler::getInstance().removeListener(SIGSEGV, this);

        extra::printStacktrace();

        exit(EXIT_FAILURE);

        break;
    }
}
}
<|endoftext|>


<commit_before>/**
 * A more complicated reduction.
 *
 * We want to represent the following program
 *
 * for y = 0 to 19
 *   for x = 0 to 9
 *     f(y, x) = 1
 *
 * for y = 0 to 19
 *   g(y) = 0
 * for y = 0 to 19
 *   for rx = 0 to 9
 *     g(y) += f(y, rx)
 *
 *
 * In order to implement this program, we create the following
 * computations
 *
 * {f[x,y]: 0<=x<19 and 0<=y<9}: 1
 * {g[y,-1]: 0<=y<19}: 0
 * {g[y,rx]: 0<=y<19 and 0<=rx<9}: g(y,rx-1) + f(y,rx)
 *
 */

#include <tiramisu/tiramisu.h>
#include "wrapper_tutorial_09.h"

using namespace tiramisu;

void generate_function(std::string name, int size, int val0)
{
    // Set default tiramisu options.
    tiramisu::init();

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------

    function function0(name);

    var x = var("x");
    var y = var("y");
    var rx = var("rx");

    computation f("{f[y,x]: 0<=y<19 and 0<=x<9}", expr((uint8_t) 1), true, p_uint8, &function0);
    computation g("{g[y,-1]: 0<=y<19}",           expr((uint8_t) 0), true, p_uint8, &function0);
    g.add_definitions("{g[y,rx]: 0<=y<19 and 0<=rx<9}", g(y,rx-1) + f(y,rx), true, p_uint8, &function0);

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------

    g.after(f, computation::root);
    g.get_update(1).after(g, computation::root);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------

    buffer f_buff("f_buff", {19,size}, p_uint8, a_temporary, &function0);
    buffer g_buff("g_buff", {size}, p_uint8, a_output, &function0);
    // Important: note that the access relations of the two computation C and C2 are identical.
    // The Tiramisu code generator assumes that the access relations of computations that have the same
    // name are identical.  In this case, the two relations are equal to "{C[j,i]->C_buff[i]}".
    f.set_access("{f[y,x]->f_buff[y,x]}");
    g.set_access("{g[y,rx]->g_buff[y]}");
    g.get_update(1).set_access("{g[y,rx]->g_buff[y]}");

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------

    function0.codegen({&g_buff}, "build/generated_fct_developers_tutorial_09.o");
}

int main(int argc, char **argv)
{
    generate_function("tiramisu_generated_code", SIZE1, 0);

    return 0;
}
<commit_msg>update tutorial_09<commit_after>/**
 * A more complicated reduction.
 *
 * We want to represent the following program
 *
 * for y = 0 to 19
 *   for x = 0 to 9
 *     f(y, x) = 1
 *
 * for y = 0 to 19
 *   g(y) = 0
 * for y = 0 to 19
 *   for rx = 0 to 9
 *     g(y) += f(y, rx)
 *
 *
 * In order to implement this program, we create the following
 * computations
 *
 * {f[x,y]: 0<=x<19 and 0<=y<9}: 1
 * {g[y,-1]: 0<=y<19}: 0
 * {g[y,rx]: 0<=y<19 and 0<=rx<9}: g(y,rx-1) + f(y,rx)
 *
 */

#include <tiramisu/tiramisu.h>
#include "wrapper_tutorial_09.h"

using namespace tiramisu;

void generate_function(std::string name, int size, int val0)
{
    // Set default tiramisu options.
    tiramisu::init();

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------

    function function0(name);

    var x = var("x");
    var y = var("y");
    var rx = var("rx");

    computation f("{f[y,x]: 0<=y<19 and 0<=x<9}", expr((uint8_t) 1), true, p_uint8, &function0);
    computation g_0("{g_0[y,-1]: 0<=y<19}",           expr((uint8_t) 0), true, p_uint8, &function0);
    computation g_1("{g_1[y,rx]: 0<=y<19 and 0<=rx<9}", g_0(y,rx-1) + f(y,rx), true, p_uint8, &function0);

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------

    g_0.after(f, computation::root);
    g_1.after(g_0, computation::root);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------

    buffer f_buff("f_buff", {19,size}, p_uint8, a_temporary, &function0);
    buffer g_buff("g_buff", {size}, p_uint8, a_output, &function0);
    f.set_access("{f[y,x]->f_buff[y,x]}");
    g_0.set_access("{g_0[y,rx]->g_buff[y]}");
    g_1.set_access("{g_1[y,rx]->g_buff[y]}");

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------

    function0.codegen({&g_buff}, "build/generated_fct_developers_tutorial_09.o");
}

int main(int argc, char **argv)
{
    generate_function("tiramisu_generated_code", SIZE1, 0);

    return 0;
}
<|endoftext|>


<commit_before>// AboutBox.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include "AboutBox.h"
#include "HeeksFrame.h"

BEGIN_EVENT_TABLE( CAboutBox, wxDialog )
EVT_BUTTON( wxID_OK, CAboutBox::OnButtonOK )
END_EVENT_TABLE()

CAboutBox::CAboutBox(wxWindow *parent):wxDialog(parent, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
{
    wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    wxButton *ok_button = new wxButton(panel, wxID_OK, _("OK"));

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

	wxTextCtrl* text_ctrl = new wxTextCtrl( this, wxID_ANY, _T(""),	wxDefaultPosition, wxSize(800,600), wxTE_READONLY | wxTE_MULTILINE);

	wxString str = wxString(_T("HeeksCAD\n see http://heeks.net, or for source code: http://code.google.com/p/heekscad/\n\nusing Open CASCADE solid modeller - http://www.opencascade.org"))
		+ wxString(_T("\n\nwindows made with wxWidgets 2.8.9 - http://wxwidgets.org"))
		+ wxString(_T("\n\ntext uses glFont Copyright (c) 1998 Brad Fish E-mail: bhf5@email.byu.edu Web: http://students.cs.byu.edu/~bfish/"))
		+ wxString(_T("\n\nWritten by:\n Dan Heeks\n Jon Pry\n Jonathan George\n David Nicholls"))
		+ wxString(_T("\n\nWith contributions from:\n Hirutso Enni\n Perttu Ahola\n Dave ( the archivist )\n mpictor\n fenn\n fungunner2\n andrea ( openSUSE )\n g_code luigi barbati"))
		+ wxString(_T("\n\nThis is free, open source software."));

	wxString version_str = wxGetApp().m_version_number;
	version_str.Replace(_T(" "), _T("."));

	this->SetTitle(version_str);

	text_ctrl->WriteText(str + wxGetApp().m_frame->m_extra_about_box_str);

    //mainsizer->Add( text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10).Expand() );
    //mainsizer->Add( ok_button, wxSizerFlags().Align(wxALIGN_CENTER) );
	mainsizer->Add( text_ctrl );
	mainsizer->Add( ok_button );
	mainsizer->RecalcSizes();

    // tell frame to make use of sizer (or constraints, if any)
    panel->SetAutoLayout( true );
    panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void CAboutBox::OnButtonOK(wxCommandEvent& event)
{
	EndModal(wxID_OK);
}
<commit_msg>small correction<commit_after>// AboutBox.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include "AboutBox.h"
#include "HeeksFrame.h"

BEGIN_EVENT_TABLE( CAboutBox, wxDialog )
EVT_BUTTON( wxID_OK, CAboutBox::OnButtonOK )
END_EVENT_TABLE()

CAboutBox::CAboutBox(wxWindow *parent):wxDialog(parent, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
{
    wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);

    wxButton *ok_button = new wxButton(panel, wxID_OK, _("OK"));

    wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );

	wxTextCtrl* text_ctrl = new wxTextCtrl( this, wxID_ANY, _T(""),	wxDefaultPosition, wxSize(800,600), wxTE_READONLY | wxTE_MULTILINE);

	wxString str = wxString(_T("HeeksCAD\n see http://heeks.net, or for source code: http://code.google.com/p/heekscad/\n\nusing Open CASCADE solid modeller - http://www.opencascade.org"))
		+ wxString(_T("\n\nwindows made with wxWidgets 2.8.9 - http://wxwidgets.org"))
		+ wxString(_T("\n\ntext uses glFont Copyright (c) 1998 Brad Fish E-mail: bhf5@email.byu.edu Web: http://students.cs.byu.edu/~bfish/"))
		+ wxString(_T("\n\nWritten by:\n Dan Heeks\n Jon Pry\n Jonathan George\n David Nicholls"))
		+ wxString(_T("\n\nWith contributions from:\n Hirutso Enni\n Perttu Ahola\n Dave ( the archivist )\n mpictor\n fenn\n fungunner2\n andrea ( openSUSE )\n g_code\n luigi barbati"))
		+ wxString(_T("\n\nThis is free, open source software."));

	wxString version_str = wxGetApp().m_version_number;
	version_str.Replace(_T(" "), _T("."));

	this->SetTitle(version_str);

	text_ctrl->WriteText(str + wxGetApp().m_frame->m_extra_about_box_str);

    //mainsizer->Add( text_ctrl, wxSizerFlags().Align(wxALIGN_CENTER).Border(wxALL, 10).Expand() );
    //mainsizer->Add( ok_button, wxSizerFlags().Align(wxALIGN_CENTER) );
	mainsizer->Add( text_ctrl );
	mainsizer->Add( ok_button );
	mainsizer->RecalcSizes();

    // tell frame to make use of sizer (or constraints, if any)
    panel->SetAutoLayout( true );
    panel->SetSizer( mainsizer );

#ifndef __WXWINCE__
    // don't allow frame to get smaller than what the sizers tell ye
    mainsizer->SetSizeHints( this );
#endif

    Show(true);
}

void CAboutBox::OnButtonOK(wxCommandEvent& event)
{
	EndModal(wxID_OK);
}
<|endoftext|>


<commit_before>#include "ofApp.h"

#include <algorithm>

#include "user.h"

// If the feature output dimension is larger than 32, making the visualization a
// single output will be more visual.
const uint32_t kTooManyFeaturesThreshold = 32;

class Palette {
  public:
    vector<ofColor> generate(uint32_t n) {
        // TODO(benzh) fill instead of re-generate.
        if (n > size) {
            size = n;
            do_generate(size);
        }

        std::vector<ofColor> sliced(colors.begin(), colors.begin() + n);
        return sliced;
    }

    Palette() : size(256) {
        do_generate(size);
    }
  private:
    void do_generate(uint32_t n) {
        uint32_t numDimensions = n;
        // Code snippet from ofxGrtTimeseriesPlot.cpp

        colors.resize(n);
        // Setup the default colors
        if( numDimensions >= 1 ) colors[0] = ofColor(255,0,0); //red
        if( numDimensions >= 2 ) colors[1] = ofColor(0,255,0); //green
        if( numDimensions >= 3 ) colors[2] = ofColor(0,0,255); //blue
        //Randomize the remaining colors
        for(unsigned int n=3; n<numDimensions; n++){
            colors[n][0] = ofRandom(50,255);
            colors[n][1] = ofRandom(50,255);
            colors[n][2] = ofRandom(50,255);
        }
    }

    uint32_t size;
    std::vector<ofColor> colors;
};

void ofApp::useStream(IStream &stream) {
    istream_ = &stream;
}

void ofApp::usePipeline(GRT::GestureRecognitionPipeline &pipeline) {
    pipeline_ = &pipeline;
}

//--------------------------------------------------------------
void ofApp::setup() {
    is_recording_ = false;

    // setup() is a user-defined function.
    ::setup();

    istream_->onDataReadyEvent(this, &ofApp::onDataIn);

    plot_inputs_.setup(kBufferSize_, istream_->getNumOutputDimensions(), "Input");
    plot_inputs_.setDrawGrid(true);
    plot_inputs_.setDrawInfoText(true);

    Palette color_palette;
    // Below is just proof-of-concept. The setup is quite hard-coded and we
    // should enrich this once the UI design is ready.
    size_t num_pre_processing = pipeline_->getNumPreProcessingModules();
    for (int i = 0; i < num_pre_processing; i++) {
        PreProcessing* pp = pipeline_->getPreProcessingModule(i);
        uint32_t dim = pp->getNumOutputDimensions();
        ofxGrtTimeseriesPlot plot;
        plot.setup(kBufferSize_, dim, "PreProcessing Stage " + std::to_string(i));
        plot.setDrawGrid(true);
        plot.setDrawInfoText(true);
        plot.setColorPalette(color_palette.generate(dim));
        plot_pre_processed_.push_back(plot);
    }

    size_t num_feature_modules = pipeline_->getNumFeatureExtractionModules();
    for (int i = 0; i < num_feature_modules; i++) {
        vector<ofxGrtTimeseriesPlot> feature_at_stage_i;

        FeatureExtraction* fe = pipeline_->getFeatureExtractionModule(i);
        uint32_t feature_dim = fe->getNumOutputDimensions();
        if (feature_dim < kTooManyFeaturesThreshold) {
            for (int i = 0; i < feature_dim; i++) {
                ofxGrtTimeseriesPlot plot;
                plot.setup(kBufferSize_, 1, "Feature " + std::to_string(i));
                plot.setDrawInfoText(true);
                plot.setColorPalette(color_palette.generate(feature_dim));
                feature_at_stage_i.push_back(plot);
            }
        } else {
            // We will have only one here.
            ofxGrtTimeseriesPlot plot;
            plot.setup(feature_dim, 1, "Feature");
            plot.setDrawInfoText(true);
            plot.setColorPalette(color_palette.generate(feature_dim));
            feature_at_stage_i.push_back(plot);
        }

        plot_features_.push_back(feature_at_stage_i);
    }

    for (int i = 0; i < kNumMaxLabels_; i++) {
        uint32_t label_dim = istream_->getNumOutputDimensions();
        ofxGrtTimeseriesPlot plot;
        plot.setup(kBufferSize_, label_dim, "Label" + std::to_string(i + 1));
        plot.setDrawInfoText(false);
        plot.setColorPalette(color_palette.generate(label_dim));
        plot.setRanges(-1, 1, true);
        plot_samples_.push_back(plot);
        plot_samples_info_.push_back("");
    }

    training_data_.setNumDimensions(istream_->getNumOutputDimensions());
//    training_data_.setDatasetName("Audio");
//    training_data_.setInfoText("This data contains audio data");
    predicted_label_ = 0;

    gui_.setup("", "", ofGetWidth() - 200, 0);
    gui_hide_ = true;
    gui_.add(save_pipeline_button_.setup("Save Pipeline", 200, 30));
    gui_.add(load_pipeline_button_.setup("Load Pipeline", 200, 30));
    save_pipeline_button_.addListener(this, &ofApp::savePipeline);
    load_pipeline_button_.addListener(this, &ofApp::loadPipeline);

    ofBackground(54, 54, 54);
}

void ofApp::savePipeline() {
    if (!pipeline_->save("pipeline.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to save the pipeline";
    }

    if (!pipeline_->getClassifier()->save("classifier.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to save the classifier";
    }
}

void ofApp::loadPipeline() {
    GRT::GestureRecognitionPipeline pipeline;
    if (!pipeline.load("pipeline.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to load the pipeline";
    }

    // TODO(benzh) Compare the two pipelines and warn the user if the
    // loaded one is different from his.
    (*pipeline_) = pipeline;
}

//--------------------------------------------------------------
void ofApp::update() {
    std::lock_guard<std::mutex> guard(input_data_mutex_);
    for (int i = 0; i < input_data_.getNumRows(); i++){
        vector<double> data_point = input_data_.getRowVector(i);

        plot_inputs_.update(data_point);

        if (istream_->hasStarted()) {
            if (!pipeline_->preProcessData(data_point)) {
                ofLog(OF_LOG_ERROR) << "ERROR: Failed to compute features!";
            }

            for (int j = 0; j < pipeline_->getNumPreProcessingModules(); j++) {
                vector<double> data = pipeline_->getPreProcessedData(j);
                plot_pre_processed_[j].update(data);
            }

            for (int j = 0; j < pipeline_->getNumFeatureExtractionModules(); j++) {
                // Working on j-th stage.
                vector<double> feature = pipeline_->getFeatureExtractionData(j);
                if (feature.size() < kTooManyFeaturesThreshold) {
                    for (int k = 0; k < feature.size(); k++) {
                        vector<double> v = { feature[k] };
                        plot_features_[j][k].update(v);
                    }
                } else {
                    assert(plot_features_.size() == 1);
                    plot_features_[j][0].setData(feature);
                }
            }
        }

        if (is_recording_) {
            sample_data_.push_back(data_point);
        }

        if (pipeline_->getTrained()) {
            pipeline_->predict(data_point);
            predicted_label_ = pipeline_->getPredictedClassLabel();
        }
    }
}

//--------------------------------------------------------------
void ofApp::draw() {
    ofSetColor(255);

    int plotX = 10;
    int plotY = 30;
    int plotW = ofGetWidth() - plotX * 2;
    int plotH = 150;
    int margin = 10;

    ofPushStyle();
    ofPushMatrix();
    {
        plot_inputs_.draw(plotX, plotY, plotW, plotH);
        plotY += plotH + margin;
    }
    ofPopStyle();
    ofPopMatrix();

    for (int i = 0; i < pipeline_->getNumPreProcessingModules(); i++) {
        // working on pre-processing stage i.
        ofPushStyle();
        ofPushMatrix();
        {
            plot_pre_processed_[i].draw(plotX, plotY, plotW, plotH);
            plotY += plotH + margin;
        }
        ofPopStyle();
        ofPopMatrix();
    }

    for (int i = 0; i < pipeline_->getNumFeatureExtractionModules(); i++) {
        // working on feature extraction stage i.
        ofPushStyle();
        ofPushMatrix();
        {
            int width = plotW / plot_features_[i].size();
            for (int j = 0; j < plot_features_[i].size(); j++) {
                plot_features_[i][j].draw(plotX + j * width, plotY, width, plotH);
            }
            plotY += plotH + margin;
        }
        ofPopStyle();
        ofPopMatrix();
    }

    // Training samples management
    ofPushStyle();
    ofPushMatrix();

    // Currently we support kNumMaxLabels_ labels
    int width = plotW / kNumMaxLabels_;
    for (int i = 0; i < kNumMaxLabels_; i++) {
        int x = plotX + i * width;
        plot_samples_[i].draw(x, plotY, width, plotH - 3 * margin);
        ofDrawBitmapString(plot_samples_info_[i], x, plotY + plotH - margin);
    }

    plotY += plotH + 3 * margin;

    ofPopStyle();
    ofPopMatrix();

    // Instructions
    ofPushStyle();
    ofPushMatrix();

    ofDrawBitmapString(std::to_string(sample_data_.getNumRows()) +
                       " data points\t" +
                       "label: " + std::to_string(predicted_label_),
                       plotX, plotY - 2.5 * margin);

    ofDrawBitmapString("Instructions: "
                       "`s` - start; `e` - pause; 1-9 training samples;"
                       "`t` - train; `h` - panel",
                       plotX, plotY - margin);

    ofPopStyle();
    ofPopMatrix();

    if (!gui_hide_) {
        gui_.draw();
    }
}

void ofApp::exit() {
    if (training_thread_.joinable()) {
        training_thread_.join();
    }
    istream_->stop();

    // Clear all listeners.
    save_pipeline_button_.removeListener(this, &ofApp::savePipeline);
    load_pipeline_button_.removeListener(this, &ofApp::loadPipeline);
}

void ofApp::onDataIn(GRT::MatrixDouble input) {
    std::lock_guard<std::mutex> guard(input_data_mutex_);
    input_data_ = input;
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if (key >= '1' && key <= '9') {
        if (!is_recording_) {
            is_recording_ = true;
            label_ = key - '0';
            sample_data_.clear();
        }
    }

    switch (key) {
        case 't': {
            // If prior training has not finished, we wait.
            if (training_thread_.joinable()) {
                training_thread_.join();
            }

            GRT::ClassificationData data_copy = training_data_;
            auto training_func = [this, data_copy]() mutable {
                ofLog() << "Training started";
                if (pipeline_->train(data_copy)) {
                    ofLog() << "Training is successful";
                } else {
                    ofLog() << "Failed to train the model";
                }
            };
            training_thread_ = std::thread(training_func);
            break;
        }

        case 'h':
            gui_hide_ = !gui_hide_;
        case 's':
            istream_->start();
            break;
        case 'e':
            istream_->stop();
            input_data_.clear();
            break;
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
    is_recording_ = false;
    if (key >= '1' && key <= '9') {
        for (int i = 0; i < sample_data_.getNumRows(); i++) {
            training_data_.addSample(label_, sample_data_.getRowVector(i));
        }

        plot_samples_[label_ - 1].setData(sample_data_);
        plot_samples_info_[label_ - 1] =
                std::to_string(sample_data_.getNumRows()) + " points";

    }
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ) {

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {

}
<commit_msg>Scale all training data plots dynamically and equally.<commit_after>#include "ofApp.h"

#include <algorithm>

#include "user.h"

// If the feature output dimension is larger than 32, making the visualization a
// single output will be more visual.
const uint32_t kTooManyFeaturesThreshold = 32;

class Palette {
  public:
    vector<ofColor> generate(uint32_t n) {
        // TODO(benzh) fill instead of re-generate.
        if (n > size) {
            size = n;
            do_generate(size);
        }

        std::vector<ofColor> sliced(colors.begin(), colors.begin() + n);
        return sliced;
    }

    Palette() : size(256) {
        do_generate(size);
    }
  private:
    void do_generate(uint32_t n) {
        uint32_t numDimensions = n;
        // Code snippet from ofxGrtTimeseriesPlot.cpp

        colors.resize(n);
        // Setup the default colors
        if( numDimensions >= 1 ) colors[0] = ofColor(255,0,0); //red
        if( numDimensions >= 2 ) colors[1] = ofColor(0,255,0); //green
        if( numDimensions >= 3 ) colors[2] = ofColor(0,0,255); //blue
        //Randomize the remaining colors
        for(unsigned int n=3; n<numDimensions; n++){
            colors[n][0] = ofRandom(50,255);
            colors[n][1] = ofRandom(50,255);
            colors[n][2] = ofRandom(50,255);
        }
    }

    uint32_t size;
    std::vector<ofColor> colors;
};

void ofApp::useStream(IStream &stream) {
    istream_ = &stream;
}

void ofApp::usePipeline(GRT::GestureRecognitionPipeline &pipeline) {
    pipeline_ = &pipeline;
}

//--------------------------------------------------------------
void ofApp::setup() {
    is_recording_ = false;

    // setup() is a user-defined function.
    ::setup();

    istream_->onDataReadyEvent(this, &ofApp::onDataIn);

    plot_inputs_.setup(kBufferSize_, istream_->getNumOutputDimensions(), "Input");
    plot_inputs_.setDrawGrid(true);
    plot_inputs_.setDrawInfoText(true);

    Palette color_palette;
    // Below is just proof-of-concept. The setup is quite hard-coded and we
    // should enrich this once the UI design is ready.
    size_t num_pre_processing = pipeline_->getNumPreProcessingModules();
    for (int i = 0; i < num_pre_processing; i++) {
        PreProcessing* pp = pipeline_->getPreProcessingModule(i);
        uint32_t dim = pp->getNumOutputDimensions();
        ofxGrtTimeseriesPlot plot;
        plot.setup(kBufferSize_, dim, "PreProcessing Stage " + std::to_string(i));
        plot.setDrawGrid(true);
        plot.setDrawInfoText(true);
        plot.setColorPalette(color_palette.generate(dim));
        plot_pre_processed_.push_back(plot);
    }

    size_t num_feature_modules = pipeline_->getNumFeatureExtractionModules();
    for (int i = 0; i < num_feature_modules; i++) {
        vector<ofxGrtTimeseriesPlot> feature_at_stage_i;

        FeatureExtraction* fe = pipeline_->getFeatureExtractionModule(i);
        uint32_t feature_dim = fe->getNumOutputDimensions();
        if (feature_dim < kTooManyFeaturesThreshold) {
            for (int i = 0; i < feature_dim; i++) {
                ofxGrtTimeseriesPlot plot;
                plot.setup(kBufferSize_, 1, "Feature " + std::to_string(i));
                plot.setDrawInfoText(true);
                plot.setColorPalette(color_palette.generate(feature_dim));
                feature_at_stage_i.push_back(plot);
            }
        } else {
            // We will have only one here.
            ofxGrtTimeseriesPlot plot;
            plot.setup(feature_dim, 1, "Feature");
            plot.setDrawInfoText(true);
            plot.setColorPalette(color_palette.generate(feature_dim));
            feature_at_stage_i.push_back(plot);
        }

        plot_features_.push_back(feature_at_stage_i);
    }

    for (int i = 0; i < kNumMaxLabels_; i++) {
        uint32_t label_dim = istream_->getNumOutputDimensions();
        ofxGrtTimeseriesPlot plot;
        plot.setup(kBufferSize_, label_dim, "Label" + std::to_string(i + 1));
        plot.setDrawInfoText(false);
        plot.setColorPalette(color_palette.generate(label_dim));
        //plot.setRanges(-1, 1, true);
        plot_samples_.push_back(plot);
        plot_samples_info_.push_back("");
    }

    training_data_.setNumDimensions(istream_->getNumOutputDimensions());
//    training_data_.setDatasetName("Audio");
//    training_data_.setInfoText("This data contains audio data");
    predicted_label_ = 0;

    gui_.setup("", "", ofGetWidth() - 200, 0);
    gui_hide_ = true;
    gui_.add(save_pipeline_button_.setup("Save Pipeline", 200, 30));
    gui_.add(load_pipeline_button_.setup("Load Pipeline", 200, 30));
    save_pipeline_button_.addListener(this, &ofApp::savePipeline);
    load_pipeline_button_.addListener(this, &ofApp::loadPipeline);

    ofBackground(54, 54, 54);
}

void ofApp::savePipeline() {
    if (!pipeline_->save("pipeline.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to save the pipeline";
    }

    if (!pipeline_->getClassifier()->save("classifier.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to save the classifier";
    }
}

void ofApp::loadPipeline() {
    GRT::GestureRecognitionPipeline pipeline;
    if (!pipeline.load("pipeline.grt")) {
        ofLog(OF_LOG_ERROR) << "Failed to load the pipeline";
    }

    // TODO(benzh) Compare the two pipelines and warn the user if the
    // loaded one is different from his.
    (*pipeline_) = pipeline;
}

//--------------------------------------------------------------
void ofApp::update() {
    std::lock_guard<std::mutex> guard(input_data_mutex_);
    for (int i = 0; i < input_data_.getNumRows(); i++){
        vector<double> data_point = input_data_.getRowVector(i);

        plot_inputs_.update(data_point);

        if (istream_->hasStarted()) {
            if (!pipeline_->preProcessData(data_point)) {
                ofLog(OF_LOG_ERROR) << "ERROR: Failed to compute features!";
            }

            for (int j = 0; j < pipeline_->getNumPreProcessingModules(); j++) {
                vector<double> data = pipeline_->getPreProcessedData(j);
                plot_pre_processed_[j].update(data);
            }

            for (int j = 0; j < pipeline_->getNumFeatureExtractionModules(); j++) {
                // Working on j-th stage.
                vector<double> feature = pipeline_->getFeatureExtractionData(j);
                if (feature.size() < kTooManyFeaturesThreshold) {
                    for (int k = 0; k < feature.size(); k++) {
                        vector<double> v = { feature[k] };
                        plot_features_[j][k].update(v);
                    }
                } else {
                    assert(plot_features_.size() == 1);
                    plot_features_[j][0].setData(feature);
                }
            }
        }

        if (is_recording_) {
            sample_data_.push_back(data_point);
        }

        if (pipeline_->getTrained()) {
            pipeline_->predict(data_point);
            predicted_label_ = pipeline_->getPredictedClassLabel();
        }
    }
}

//--------------------------------------------------------------
void ofApp::draw() {
    ofSetColor(255);

    int plotX = 10;
    int plotY = 30;
    int plotW = ofGetWidth() - plotX * 2;
    int plotH = 150;
    int margin = 10;

    ofPushStyle();
    ofPushMatrix();
    {
        plot_inputs_.draw(plotX, plotY, plotW, plotH);
        plotY += plotH + margin;
    }
    ofPopStyle();
    ofPopMatrix();

    for (int i = 0; i < pipeline_->getNumPreProcessingModules(); i++) {
        // working on pre-processing stage i.
        ofPushStyle();
        ofPushMatrix();
        {
            plot_pre_processed_[i].draw(plotX, plotY, plotW, plotH);
            plotY += plotH + margin;
        }
        ofPopStyle();
        ofPopMatrix();
    }

    for (int i = 0; i < pipeline_->getNumFeatureExtractionModules(); i++) {
        // working on feature extraction stage i.
        ofPushStyle();
        ofPushMatrix();
        {
            int width = plotW / plot_features_[i].size();
            for (int j = 0; j < plot_features_[i].size(); j++) {
                plot_features_[i][j].draw(plotX + j * width, plotY, width, plotH);
            }
            plotY += plotH + margin;
        }
        ofPopStyle();
        ofPopMatrix();
    }

    // Training samples management
    ofPushStyle();
    ofPushMatrix();

    // Currently we support kNumMaxLabels_ labels
    int width = plotW / kNumMaxLabels_;
    int minY = plot_samples_[0].getRanges().first;
    int maxY = plot_samples_[0].getRanges().second;
    for (int i = 1; i < kNumMaxLabels_; i++) {
        if (plot_samples_[i].getRanges().first < minY) minY = plot_samples_[i].getRanges().first;
        if (plot_samples_[i].getRanges().second > maxY) maxY = plot_samples_[i].getRanges().second;
    }
    for (int i = 0; i < kNumMaxLabels_; i++) {
        int x = plotX + i * width;
        plot_samples_[i].setRanges(minY, maxY, true);
        plot_samples_[i].draw(x, plotY, width, plotH - 3 * margin);
        ofDrawBitmapString(plot_samples_info_[i], x, plotY + plotH - margin);
    }

    plotY += plotH + 3 * margin;

    ofPopStyle();
    ofPopMatrix();

    // Instructions
    ofPushStyle();
    ofPushMatrix();

    ofDrawBitmapString(std::to_string(sample_data_.getNumRows()) +
                       " data points\t" +
                       "label: " + std::to_string(predicted_label_),
                       plotX, plotY - 2.5 * margin);

    ofDrawBitmapString("Instructions: "
                       "`s` - start; `e` - pause; 1-9 training samples;"
                       "`t` - train; `h` - panel",
                       plotX, plotY - margin);

    ofPopStyle();
    ofPopMatrix();

    if (!gui_hide_) {
        gui_.draw();
    }
}

void ofApp::exit() {
    if (training_thread_.joinable()) {
        training_thread_.join();
    }
    istream_->stop();

    // Clear all listeners.
    save_pipeline_button_.removeListener(this, &ofApp::savePipeline);
    load_pipeline_button_.removeListener(this, &ofApp::loadPipeline);
}

void ofApp::onDataIn(GRT::MatrixDouble input) {
    std::lock_guard<std::mutex> guard(input_data_mutex_);
    input_data_ = input;
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if (key >= '1' && key <= '9') {
        if (!is_recording_) {
            is_recording_ = true;
            label_ = key - '0';
            sample_data_.clear();
        }
    }

    switch (key) {
        case 't': {
            // If prior training has not finished, we wait.
            if (training_thread_.joinable()) {
                training_thread_.join();
            }

            GRT::ClassificationData data_copy = training_data_;
            auto training_func = [this, data_copy]() mutable {
                ofLog() << "Training started";
                if (pipeline_->train(data_copy)) {
                    ofLog() << "Training is successful";
                } else {
                    ofLog() << "Failed to train the model";
                }
            };
            training_thread_ = std::thread(training_func);
            break;
        }

        case 'h':
            gui_hide_ = !gui_hide_;
        case 's':
            istream_->start();
            break;
        case 'e':
            istream_->stop();
            input_data_.clear();
            break;
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
    is_recording_ = false;
    if (key >= '1' && key <= '9') {
        for (int i = 0; i < sample_data_.getNumRows(); i++) {
            training_data_.addSample(label_, sample_data_.getRowVector(i));
        }

        plot_samples_[label_ - 1].setData(sample_data_);
        plot_samples_info_[label_ - 1] =
                std::to_string(sample_data_.getNumRows()) + " points";

    }
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ) {

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {

}
<|endoftext|>