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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkBoundingShapeVtkMapper3D.h"
#include "../DataManagement/mitkBoundingShapeUtil.h"
#include <mitkBaseProperty.h>
#include <vtkAppendPolyData.h>
#include <vtkCamera.h>
#include <vtkCubeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkMath.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkSphereSource.h>
#include <vtkTransformFilter.h>

namespace mitk
{
  class BoundingShapeVtkMapper3D::Impl
  {
    class LocalStorage : public Mapper::BaseLocalStorage
    {
    public:
      LocalStorage();
      ~LocalStorage();

      LocalStorage(const LocalStorage &) = delete;
      LocalStorage &operator=(const LocalStorage &) = delete;

      std::vector<vtkSmartPointer<vtkSphereSource>> Handles;
      vtkSmartPointer<vtkActor> Actor;
      vtkSmartPointer<vtkActor> HandleActor;
      vtkSmartPointer<vtkActor> SelectedHandleActor;
      vtkSmartPointer<vtkPropAssembly> PropAssembly;
    };

  public:
    Impl() : DistanceFromCam(1.0)
    {
      Point3D initialPoint;
      initialPoint.Fill(0);

      for (int i = 0; i < 6; ++i)
        HandlePropertyList.push_back(Handle(initialPoint, i, GetHandleIndices(i)));
    }

    double DistanceFromCam;
    std::vector<Handle> HandlePropertyList;
    mitk::LocalStorageHandler<LocalStorage> LocalStorageHandler;
  };
}

mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::LocalStorage()
  : Actor(vtkSmartPointer<vtkActor>::New()),
    HandleActor(vtkSmartPointer<vtkActor>::New()),
    SelectedHandleActor(vtkSmartPointer<vtkActor>::New()),
    PropAssembly(vtkSmartPointer<vtkPropAssembly>::New())
{
  for (int i = 0; i < 6; i++)
    Handles.push_back(vtkSmartPointer<vtkSphereSource>::New());
}

mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::~LocalStorage()
{
}

void mitk::BoundingShapeVtkMapper3D::SetDefaultProperties(DataNode *node, BaseRenderer *renderer, bool overwrite)
{
  Superclass::SetDefaultProperties(node, renderer, overwrite);
}

mitk::BoundingShapeVtkMapper3D::BoundingShapeVtkMapper3D() : m_Impl(new Impl)
{
}

mitk::BoundingShapeVtkMapper3D::~BoundingShapeVtkMapper3D()
{
  delete m_Impl;
}

void mitk::BoundingShapeVtkMapper3D::ApplyColorAndOpacityProperties(BaseRenderer *renderer, vtkActor *actor)
{
  //Superclass::ApplyColorAndOpacityProperties(renderer, actor);
}

void mitk::BoundingShapeVtkMapper3D::ApplyBoundingShapeProperties(BaseRenderer *renderer, vtkActor *actor)
{
  if (actor == nullptr)
    return;

  auto dataNode = this->GetDataNode();

  if (dataNode == nullptr)
    return;

  bool isVisible = false;
  dataNode->GetBoolProperty("Bounding Shape.3D Rendering", isVisible, renderer);

  actor->SetVisibility(isVisible);

  float lineWidth = 1.0f;
  dataNode->GetFloatProperty("Bounding Shape.Line.Width", lineWidth, renderer);

  auto property = actor->GetProperty();
  property->SetLineWidth(lineWidth);
}

void mitk::BoundingShapeVtkMapper3D::GenerateDataForRenderer(BaseRenderer *renderer)
{
  auto dataNode = this->GetDataNode();

  if (dataNode == nullptr)
    return;

  vtkCamera *camera = renderer->GetVtkRenderer()->GetActiveCamera();

  auto localStorage = m_Impl->LocalStorageHandler.GetLocalStorage(renderer);
  bool needGenerateData = localStorage->GetLastGenerateDataTime() < dataNode->GetMTime();
  double distance = camera->GetDistance();

  if (std::abs(distance - m_Impl->DistanceFromCam) > mitk::eps)
  {
    m_Impl->DistanceFromCam = distance;
    needGenerateData = true;
  }

  if (needGenerateData)
  {
    bool isVisible = true;
    dataNode->GetVisibility(isVisible, renderer);

    if (!isVisible)
    {
      localStorage->Actor->VisibilityOff();
      return;
    }

    // set the input-object at time t for the mapper
    GeometryData *geometryData = dynamic_cast<GeometryData *>(dataNode->GetData());
    if (geometryData == nullptr)
      return;

    mitk::BaseGeometry::Pointer geometry = geometryData->GetGeometry();
    mitk::Vector3D spacing = geometry->GetSpacing();

    // calculate cornerpoints from geometry
    std::vector<Point3D> cornerPoints = GetCornerPoints(geometry, true);

    Point3D p0 = cornerPoints[0];
    Point3D p1 = cornerPoints[1];
    Point3D p2 = cornerPoints[2];
    Point3D p4 = cornerPoints[4];

    Point3D extent;
    extent[0] =
      sqrt((p0[0] - p4[0]) * (p0[0] - p4[0]) + (p0[1] - p4[1]) * (p0[1] - p4[1]) + (p0[2] - p4[2]) * (p0[2] - p4[2]));
    extent[1] =
      sqrt((p0[0] - p2[0]) * (p0[0] - p2[0]) + (p0[1] - p2[1]) * (p0[1] - p2[1]) + (p0[2] - p2[2]) * (p0[2] - p2[2]));
    extent[2] =
      sqrt((p0[0] - p1[0]) * (p0[0] - p1[0]) + (p0[1] - p1[1]) * (p0[1] - p1[1]) + (p0[2] - p1[2]) * (p0[2] - p1[2]));

    // calculate center based on half way of the distance between two opposing cornerpoints
    mitk::Point3D center = CalcAvgPoint(cornerPoints[7], cornerPoints[0]);

    if (m_Impl->HandlePropertyList.size() == 6)
    {
      // set handle positions
      Point3D pointLeft = CalcAvgPoint(cornerPoints[5], cornerPoints[6]);
      Point3D pointRight = CalcAvgPoint(cornerPoints[1], cornerPoints[2]);
      Point3D pointTop = CalcAvgPoint(cornerPoints[0], cornerPoints[6]);
      Point3D pointBottom = CalcAvgPoint(cornerPoints[7], cornerPoints[1]);
      Point3D pointFront = CalcAvgPoint(cornerPoints[2], cornerPoints[7]);
      Point3D pointBack = CalcAvgPoint(cornerPoints[4], cornerPoints[1]);

      m_Impl->HandlePropertyList[0].SetPosition(pointLeft);
      m_Impl->HandlePropertyList[1].SetPosition(pointRight);
      m_Impl->HandlePropertyList[2].SetPosition(pointTop);
      m_Impl->HandlePropertyList[3].SetPosition(pointBottom);
      m_Impl->HandlePropertyList[4].SetPosition(pointFront);
      m_Impl->HandlePropertyList[5].SetPosition(pointBack);
    }

    auto cube = vtkCubeSource::New();
    cube->SetXLength(extent[0] / spacing[0]);
    cube->SetYLength(extent[1] / spacing[1]);
    cube->SetZLength(extent[2] / spacing[2]);

    // calculates translation based on offset+extent not on the transformation matrix
    vtkSmartPointer<vtkMatrix4x4> imageTransform = geometry->GetVtkTransform()->GetMatrix();
    auto translation = vtkSmartPointer<vtkTransform>::New();
    translation->Translate(center[0] - imageTransform->GetElement(0, 3),
                           center[1] - imageTransform->GetElement(1, 3),
                           center[2] - imageTransform->GetElement(2, 3));

    auto transform = vtkSmartPointer<vtkTransform>::New();
    transform->SetMatrix(imageTransform);
    transform->PostMultiply();
    transform->Concatenate(translation);
    transform->Update();
    cube->Update();

    auto transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
    transformFilter->SetInputData(cube->GetOutput());
    transformFilter->SetTransform(transform);
    transformFilter->Update();
    cube->Delete();

    vtkSmartPointer<vtkPolyData> polydata = transformFilter->GetPolyDataOutput();
    if (polydata == nullptr)
    {
      localStorage->Actor->VisibilityOff();
      return;
    }

    mitk::DoubleProperty::Pointer handleSizeProperty =
      dynamic_cast<mitk::DoubleProperty *>(this->GetDataNode()->GetProperty("Bounding Shape.Handle Size Factor"));

    ScalarType initialHandleSize;
    if (handleSizeProperty != nullptr)
      initialHandleSize = handleSizeProperty->GetValue();
    else
      initialHandleSize = 1.0 / 40.0;

    double handlesize =
      ((camera->GetDistance() * std::tan(vtkMath::RadiansFromDegrees(camera->GetViewAngle()))) / 2.0) *
      initialHandleSize;

    if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->HandleActor))
      localStorage->PropAssembly->RemovePart(localStorage->HandleActor);
    if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->Actor))
      localStorage->PropAssembly->RemovePart(localStorage->Actor);

    auto selectedhandlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    auto appendPoly = vtkSmartPointer<vtkAppendPolyData>::New();

    mitk::IntProperty::Pointer activeHandleId =
      dynamic_cast<mitk::IntProperty *>(dataNode->GetProperty("Bounding Shape.Active Handle ID"));

    int i = 0;
    for (auto &handle : localStorage->Handles)
    {
      Point3D handlecenter = m_Impl->HandlePropertyList[i].GetPosition();
      handle->SetCenter(handlecenter[0], handlecenter[1], handlecenter[2]);
      handle->SetRadius(handlesize);
      handle->Update();
      if (activeHandleId == nullptr)
      {
        appendPoly->AddInputConnection(handle->GetOutputPort());
      }
      else
      {
        if (activeHandleId->GetValue() != m_Impl->HandlePropertyList[i].GetIndex())
        {
          appendPoly->AddInputConnection(handle->GetOutputPort());
        }
        else
        {
          selectedhandlemapper->SetInputData(handle->GetOutput());
          localStorage->SelectedHandleActor->SetMapper(selectedhandlemapper);
          localStorage->SelectedHandleActor->GetProperty()->SetColor(0, 1, 0);
          localStorage->SelectedHandleActor->GetMapper()->SetInputDataObject(handle->GetOutput());
          localStorage->PropAssembly->AddPart(localStorage->SelectedHandleActor);
        }
      }
      i++;
    }
    appendPoly->Update();

    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputData(polydata);

    auto handlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    handlemapper->SetInputData(appendPoly->GetOutput());

    localStorage->Actor->SetMapper(mapper);
    localStorage->Actor->GetMapper()->SetInputDataObject(polydata);
    localStorage->Actor->GetProperty()->SetOpacity(0.3);

    mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty *>(dataNode->GetProperty("color"));
    if (selectedColor != nullptr)
    {
      mitk::Color color = selectedColor->GetColor();
      localStorage->Actor->GetProperty()->SetColor(color[0], color[1], color[2]);
    }

    localStorage->HandleActor->SetMapper(handlemapper);
    if (activeHandleId == nullptr)
    {
      localStorage->HandleActor->GetProperty()->SetColor(1, 1, 1);
    }
    else
    {
      localStorage->HandleActor->GetProperty()->SetColor(1, 0, 0);
    }

    localStorage->HandleActor->GetMapper()->SetInputDataObject(appendPoly->GetOutput());

    this->ApplyColorAndOpacityProperties(renderer, localStorage->Actor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->Actor);

    this->ApplyColorAndOpacityProperties(renderer, localStorage->HandleActor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->HandleActor);

    this->ApplyColorAndOpacityProperties(renderer, localStorage->SelectedHandleActor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->SelectedHandleActor);

    // apply properties read from the PropertyList
    // this->ApplyProperties(localStorage->m_Actor, renderer);
    // this->ApplyProperties(localStorage->m_HandleActor, renderer);
    // this->ApplyProperties(localStorage->m_SelectedHandleActor, renderer);

    localStorage->Actor->VisibilityOn();
    localStorage->HandleActor->VisibilityOn();
    localStorage->SelectedHandleActor->VisibilityOn();

    localStorage->PropAssembly->AddPart(localStorage->Actor);
    localStorage->PropAssembly->AddPart(localStorage->HandleActor);
    localStorage->PropAssembly->VisibilityOn();

    localStorage->UpdateGenerateDataTime();
  }
}
vtkProp *mitk::BoundingShapeVtkMapper3D::GetVtkProp(BaseRenderer *renderer)
{
  return m_Impl->LocalStorageHandler.GetLocalStorage(renderer)->PropAssembly;
}
<commit_msg>removed unused function parameter<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkBoundingShapeVtkMapper3D.h"
#include "../DataManagement/mitkBoundingShapeUtil.h"
#include <mitkBaseProperty.h>
#include <vtkAppendPolyData.h>
#include <vtkCamera.h>
#include <vtkCubeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkMath.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkSphereSource.h>
#include <vtkTransformFilter.h>

namespace mitk
{
  class BoundingShapeVtkMapper3D::Impl
  {
    class LocalStorage : public Mapper::BaseLocalStorage
    {
    public:
      LocalStorage();
      ~LocalStorage();

      LocalStorage(const LocalStorage &) = delete;
      LocalStorage &operator=(const LocalStorage &) = delete;

      std::vector<vtkSmartPointer<vtkSphereSource>> Handles;
      vtkSmartPointer<vtkActor> Actor;
      vtkSmartPointer<vtkActor> HandleActor;
      vtkSmartPointer<vtkActor> SelectedHandleActor;
      vtkSmartPointer<vtkPropAssembly> PropAssembly;
    };

  public:
    Impl() : DistanceFromCam(1.0)
    {
      Point3D initialPoint;
      initialPoint.Fill(0);

      for (int i = 0; i < 6; ++i)
        HandlePropertyList.push_back(Handle(initialPoint, i, GetHandleIndices(i)));
    }

    double DistanceFromCam;
    std::vector<Handle> HandlePropertyList;
    mitk::LocalStorageHandler<LocalStorage> LocalStorageHandler;
  };
}

mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::LocalStorage()
  : Actor(vtkSmartPointer<vtkActor>::New()),
    HandleActor(vtkSmartPointer<vtkActor>::New()),
    SelectedHandleActor(vtkSmartPointer<vtkActor>::New()),
    PropAssembly(vtkSmartPointer<vtkPropAssembly>::New())
{
  for (int i = 0; i < 6; i++)
    Handles.push_back(vtkSmartPointer<vtkSphereSource>::New());
}

mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::~LocalStorage()
{
}

void mitk::BoundingShapeVtkMapper3D::SetDefaultProperties(DataNode *node, BaseRenderer *renderer, bool overwrite)
{
  Superclass::SetDefaultProperties(node, renderer, overwrite);
}

mitk::BoundingShapeVtkMapper3D::BoundingShapeVtkMapper3D() : m_Impl(new Impl)
{
}

mitk::BoundingShapeVtkMapper3D::~BoundingShapeVtkMapper3D()
{
  delete m_Impl;
}

void mitk::BoundingShapeVtkMapper3D::ApplyColorAndOpacityProperties(BaseRenderer*, vtkActor*)
{
  //Superclass::ApplyColorAndOpacityProperties(renderer, actor);
}

void mitk::BoundingShapeVtkMapper3D::ApplyBoundingShapeProperties(BaseRenderer *renderer, vtkActor *actor)
{
  if (actor == nullptr)
    return;

  auto dataNode = this->GetDataNode();

  if (dataNode == nullptr)
    return;

  bool isVisible = false;
  dataNode->GetBoolProperty("Bounding Shape.3D Rendering", isVisible, renderer);

  actor->SetVisibility(isVisible);

  float lineWidth = 1.0f;
  dataNode->GetFloatProperty("Bounding Shape.Line.Width", lineWidth, renderer);

  auto property = actor->GetProperty();
  property->SetLineWidth(lineWidth);
}

void mitk::BoundingShapeVtkMapper3D::GenerateDataForRenderer(BaseRenderer *renderer)
{
  auto dataNode = this->GetDataNode();

  if (dataNode == nullptr)
    return;

  vtkCamera *camera = renderer->GetVtkRenderer()->GetActiveCamera();

  auto localStorage = m_Impl->LocalStorageHandler.GetLocalStorage(renderer);
  bool needGenerateData = localStorage->GetLastGenerateDataTime() < dataNode->GetMTime();
  double distance = camera->GetDistance();

  if (std::abs(distance - m_Impl->DistanceFromCam) > mitk::eps)
  {
    m_Impl->DistanceFromCam = distance;
    needGenerateData = true;
  }

  if (needGenerateData)
  {
    bool isVisible = true;
    dataNode->GetVisibility(isVisible, renderer);

    if (!isVisible)
    {
      localStorage->Actor->VisibilityOff();
      return;
    }

    // set the input-object at time t for the mapper
    GeometryData *geometryData = dynamic_cast<GeometryData *>(dataNode->GetData());
    if (geometryData == nullptr)
      return;

    mitk::BaseGeometry::Pointer geometry = geometryData->GetGeometry();
    mitk::Vector3D spacing = geometry->GetSpacing();

    // calculate cornerpoints from geometry
    std::vector<Point3D> cornerPoints = GetCornerPoints(geometry, true);

    Point3D p0 = cornerPoints[0];
    Point3D p1 = cornerPoints[1];
    Point3D p2 = cornerPoints[2];
    Point3D p4 = cornerPoints[4];

    Point3D extent;
    extent[0] =
      sqrt((p0[0] - p4[0]) * (p0[0] - p4[0]) + (p0[1] - p4[1]) * (p0[1] - p4[1]) + (p0[2] - p4[2]) * (p0[2] - p4[2]));
    extent[1] =
      sqrt((p0[0] - p2[0]) * (p0[0] - p2[0]) + (p0[1] - p2[1]) * (p0[1] - p2[1]) + (p0[2] - p2[2]) * (p0[2] - p2[2]));
    extent[2] =
      sqrt((p0[0] - p1[0]) * (p0[0] - p1[0]) + (p0[1] - p1[1]) * (p0[1] - p1[1]) + (p0[2] - p1[2]) * (p0[2] - p1[2]));

    // calculate center based on half way of the distance between two opposing cornerpoints
    mitk::Point3D center = CalcAvgPoint(cornerPoints[7], cornerPoints[0]);

    if (m_Impl->HandlePropertyList.size() == 6)
    {
      // set handle positions
      Point3D pointLeft = CalcAvgPoint(cornerPoints[5], cornerPoints[6]);
      Point3D pointRight = CalcAvgPoint(cornerPoints[1], cornerPoints[2]);
      Point3D pointTop = CalcAvgPoint(cornerPoints[0], cornerPoints[6]);
      Point3D pointBottom = CalcAvgPoint(cornerPoints[7], cornerPoints[1]);
      Point3D pointFront = CalcAvgPoint(cornerPoints[2], cornerPoints[7]);
      Point3D pointBack = CalcAvgPoint(cornerPoints[4], cornerPoints[1]);

      m_Impl->HandlePropertyList[0].SetPosition(pointLeft);
      m_Impl->HandlePropertyList[1].SetPosition(pointRight);
      m_Impl->HandlePropertyList[2].SetPosition(pointTop);
      m_Impl->HandlePropertyList[3].SetPosition(pointBottom);
      m_Impl->HandlePropertyList[4].SetPosition(pointFront);
      m_Impl->HandlePropertyList[5].SetPosition(pointBack);
    }

    auto cube = vtkCubeSource::New();
    cube->SetXLength(extent[0] / spacing[0]);
    cube->SetYLength(extent[1] / spacing[1]);
    cube->SetZLength(extent[2] / spacing[2]);

    // calculates translation based on offset+extent not on the transformation matrix
    vtkSmartPointer<vtkMatrix4x4> imageTransform = geometry->GetVtkTransform()->GetMatrix();
    auto translation = vtkSmartPointer<vtkTransform>::New();
    translation->Translate(center[0] - imageTransform->GetElement(0, 3),
                           center[1] - imageTransform->GetElement(1, 3),
                           center[2] - imageTransform->GetElement(2, 3));

    auto transform = vtkSmartPointer<vtkTransform>::New();
    transform->SetMatrix(imageTransform);
    transform->PostMultiply();
    transform->Concatenate(translation);
    transform->Update();
    cube->Update();

    auto transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
    transformFilter->SetInputData(cube->GetOutput());
    transformFilter->SetTransform(transform);
    transformFilter->Update();
    cube->Delete();

    vtkSmartPointer<vtkPolyData> polydata = transformFilter->GetPolyDataOutput();
    if (polydata == nullptr)
    {
      localStorage->Actor->VisibilityOff();
      return;
    }

    mitk::DoubleProperty::Pointer handleSizeProperty =
      dynamic_cast<mitk::DoubleProperty *>(this->GetDataNode()->GetProperty("Bounding Shape.Handle Size Factor"));

    ScalarType initialHandleSize;
    if (handleSizeProperty != nullptr)
      initialHandleSize = handleSizeProperty->GetValue();
    else
      initialHandleSize = 1.0 / 40.0;

    double handlesize =
      ((camera->GetDistance() * std::tan(vtkMath::RadiansFromDegrees(camera->GetViewAngle()))) / 2.0) *
      initialHandleSize;

    if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->HandleActor))
      localStorage->PropAssembly->RemovePart(localStorage->HandleActor);
    if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->Actor))
      localStorage->PropAssembly->RemovePart(localStorage->Actor);

    auto selectedhandlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    auto appendPoly = vtkSmartPointer<vtkAppendPolyData>::New();

    mitk::IntProperty::Pointer activeHandleId =
      dynamic_cast<mitk::IntProperty *>(dataNode->GetProperty("Bounding Shape.Active Handle ID"));

    int i = 0;
    for (auto &handle : localStorage->Handles)
    {
      Point3D handlecenter = m_Impl->HandlePropertyList[i].GetPosition();
      handle->SetCenter(handlecenter[0], handlecenter[1], handlecenter[2]);
      handle->SetRadius(handlesize);
      handle->Update();
      if (activeHandleId == nullptr)
      {
        appendPoly->AddInputConnection(handle->GetOutputPort());
      }
      else
      {
        if (activeHandleId->GetValue() != m_Impl->HandlePropertyList[i].GetIndex())
        {
          appendPoly->AddInputConnection(handle->GetOutputPort());
        }
        else
        {
          selectedhandlemapper->SetInputData(handle->GetOutput());
          localStorage->SelectedHandleActor->SetMapper(selectedhandlemapper);
          localStorage->SelectedHandleActor->GetProperty()->SetColor(0, 1, 0);
          localStorage->SelectedHandleActor->GetMapper()->SetInputDataObject(handle->GetOutput());
          localStorage->PropAssembly->AddPart(localStorage->SelectedHandleActor);
        }
      }
      i++;
    }
    appendPoly->Update();

    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputData(polydata);

    auto handlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    handlemapper->SetInputData(appendPoly->GetOutput());

    localStorage->Actor->SetMapper(mapper);
    localStorage->Actor->GetMapper()->SetInputDataObject(polydata);
    localStorage->Actor->GetProperty()->SetOpacity(0.3);

    mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty *>(dataNode->GetProperty("color"));
    if (selectedColor != nullptr)
    {
      mitk::Color color = selectedColor->GetColor();
      localStorage->Actor->GetProperty()->SetColor(color[0], color[1], color[2]);
    }

    localStorage->HandleActor->SetMapper(handlemapper);
    if (activeHandleId == nullptr)
    {
      localStorage->HandleActor->GetProperty()->SetColor(1, 1, 1);
    }
    else
    {
      localStorage->HandleActor->GetProperty()->SetColor(1, 0, 0);
    }

    localStorage->HandleActor->GetMapper()->SetInputDataObject(appendPoly->GetOutput());

    this->ApplyColorAndOpacityProperties(renderer, localStorage->Actor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->Actor);

    this->ApplyColorAndOpacityProperties(renderer, localStorage->HandleActor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->HandleActor);

    this->ApplyColorAndOpacityProperties(renderer, localStorage->SelectedHandleActor);
    this->ApplyBoundingShapeProperties(renderer, localStorage->SelectedHandleActor);

    // apply properties read from the PropertyList
    // this->ApplyProperties(localStorage->m_Actor, renderer);
    // this->ApplyProperties(localStorage->m_HandleActor, renderer);
    // this->ApplyProperties(localStorage->m_SelectedHandleActor, renderer);

    localStorage->Actor->VisibilityOn();
    localStorage->HandleActor->VisibilityOn();
    localStorage->SelectedHandleActor->VisibilityOn();

    localStorage->PropAssembly->AddPart(localStorage->Actor);
    localStorage->PropAssembly->AddPart(localStorage->HandleActor);
    localStorage->PropAssembly->VisibilityOn();

    localStorage->UpdateGenerateDataTime();
  }
}
vtkProp *mitk::BoundingShapeVtkMapper3D::GetVtkProp(BaseRenderer *renderer)
{
  return m_Impl->LocalStorageHandler.GetLocalStorage(renderer)->PropAssembly;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP

// mapnik
#include <mapnik/warp.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/feature.hpp>

// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_gray.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"

namespace mapnik {

namespace detail {

template <typename F>
struct image_data_dispatcher :  util::static_visitor<void>
{
    using composite_function = F;
    image_data_dispatcher(int start_x, int start_y,
                          int width, int height,
                          double scale_x, double scale_y,
                          scaling_method_e method, double filter_factor,
                          double opacity, composite_mode_e comp_op,
                          raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional<double> const& nodata)
        : start_x_(start_x),
          start_y_(start_y),
          width_(width),
          height_(height),
          scale_x_(scale_x),
          scale_y_(scale_y),
          method_(method),
          filter_factor_(filter_factor),
        opacity_(opacity),
        comp_op_(comp_op),
        sym_(sym),
        feature_(feature),
        composite_(composite),
        nodata_(nodata) {}

    void operator() (image_data_null const& data_in) const {}  //no-op
    void operator() (image_data_rgba8 const& data_in) const
    {
        image_data_rgba8 data_out(width_, height_);
        scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
        composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
    }

    template <typename T>
    void operator() (T const& data_in) const
    {
        using image_data_type = T;
        image_data_type data_out(width_, height_);
        scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
        image_data_rgba8 dst(width_, height_);
        raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
        if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
        composite_(dst, comp_op_, opacity_, start_x_, start_y_);
    }
private:
    int start_x_;
    int start_y_;
    int width_;
    int height_;
    double scale_x_;
    double scale_y_;
    scaling_method_e method_;
    double filter_factor_;
    double opacity_;
    composite_mode_e comp_op_;
    raster_symbolizer const& sym_;
    feature_impl const& feature_;
    composite_function & composite_;
    boost::optional<double> const& nodata_;
};

template <typename F>
struct image_data_warp_dispatcher :  util::static_visitor<void>
{
    using composite_function = F;
    image_data_warp_dispatcher(proj_transform const& prj_trans,
                               int start_x, int start_y, int width, int height,
                               box2d<double> const& target_ext, box2d<double> const& source_ext,
                               double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method,
                               double filter_factor, double opacity, composite_mode_e comp_op,
                               raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional<double> const& nodata)
        : prj_trans_(prj_trans),
        start_x_(start_x),
        start_y_(start_y),
        width_(width),
        height_(height),
        target_ext_(target_ext),
        source_ext_(source_ext),
        offset_x_(offset_x),
        offset_y_(offset_y),
        mesh_size_(mesh_size),
        scaling_method_(scaling_method),
        filter_factor_(filter_factor),
        opacity_(opacity),
        comp_op_(comp_op),
        sym_(sym),
        feature_(feature),
        composite_(composite),
        nodata_(nodata) {}

    void operator() (image_data_null const& data_in) const {} //no-op

    void operator() (image_data_rgba8 const& data_in) const
    {
        image_data_rgba8 data_out(width_, height_);
        warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
        composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
    }

    template <typename T>
    void operator() (T const& data_in) const
    {
        using image_data_type = T;
        image_data_type data_out(width_, height_);
        warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
        image_data_rgba8 dst(width_, height_);
        raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
        if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
        composite_(dst, comp_op_, opacity_, start_x_, start_y_);
    }
private:
    proj_transform const& prj_trans_;
    int start_x_;
    int start_y_;
    int width_;
    int height_;
    box2d<double> const& target_ext_;
    box2d<double> const& source_ext_;
    double offset_x_;
    double offset_y_;
    unsigned mesh_size_;
    scaling_method_e scaling_method_;
    double filter_factor_;
    double opacity_;
    composite_mode_e comp_op_;
    raster_symbolizer const& sym_;
    feature_impl const& feature_;
    composite_function & composite_;
    boost::optional<double> const& nodata_;
};

}

template <typename F>
void render_raster_symbolizer(raster_symbolizer const& sym,
                              mapnik::feature_impl& feature,
                              proj_transform const& prj_trans,
                              renderer_common& common,
                              F composite)
{
    raster_ptr const& source = feature.get_raster();
    if (source)
    {
        box2d<double> target_ext = box2d<double>(source->ext_);
        prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
        box2d<double> ext = common.t_.forward(target_ext);
        int start_x = static_cast<int>(std::floor(ext.minx()+.5));
        int start_y = static_cast<int>(std::floor(ext.miny()+.5));
        int end_x = static_cast<int>(std::floor(ext.maxx()+.5));
        int end_y = static_cast<int>(std::floor(ext.maxy()+.5));
        int raster_width = end_x - start_x;
        int raster_height = end_y - start_y;
        if (raster_width > 0 && raster_height > 0)
        {
            scaling_method_e scaling_method = get<scaling_method_e>(sym, keys::scaling, feature, common.vars_, SCALING_NEAR);
            composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common.vars_, src_over);
            double opacity = get<double>(sym,keys::opacity,feature, common.vars_, 1.0);
            bool premultiply_source = !source->premultiplied_alpha_;
            auto is_premultiplied = get_optional<bool>(sym, keys::premultiplied, feature, common.vars_);
            if (is_premultiplied)
            {
                if (*is_premultiplied) premultiply_source = false;
                else premultiply_source = true;
            }
            // only premuiltiply rgba8 images
            if (premultiply_source && source->data_.is<image_data_rgba8>())
            {
                agg::rendering_buffer buffer(source->data_.getBytes(),
                                             source->data_.width(),
                                             source->data_.height(),
                                             source->data_.width() * 4);
                agg::pixfmt_rgba32 pixf(buffer);
                pixf.premultiply();
            }

            if (!prj_trans.equal())
            {
                double offset_x = ext.minx() - start_x;
                double offset_y = ext.miny() - start_y;
                unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16));
                detail::image_data_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
                                                                 target_ext, source->ext_, offset_x, offset_y, mesh_size,
                                                                 scaling_method, source->get_filter_factor(),
                                                                 opacity, comp_op, sym, feature, composite, source->nodata());
                util::apply_visitor(dispatcher, source->data_);
            }
            else
            {
                double image_ratio_x = ext.width() / source->data_.width();
                double image_ratio_y = ext.height() / source->data_.height();
                double eps = 1e-5;
                if ( (std::fabs(image_ratio_x - 1.0) <= eps) &&
                     (std::fabs(image_ratio_y - 1.0) <= eps) &&
                     (std::abs(start_x) <= eps) &&
                     (std::abs(start_y) <= eps) )
                {
                    if (source->data_.is<image_data_rgba8>())
                    {
                        composite(util::get<image_data_rgba8>(source->data_), comp_op, opacity, start_x, start_y);
                    }
                }
                else
                {
                    detail::image_data_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
                                                                image_ratio_x, image_ratio_y,
                                                                scaling_method, source->get_filter_factor(),
                                                                opacity, comp_op, sym, feature, composite, source->nodata());
                    util::apply_visitor(dispatcher, source->data_);
                }
            }
        }
    }
}

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
<commit_msg>warp - initialise target with nodata if available<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP

// mapnik
#include <mapnik/warp.hpp>
#include <mapnik/raster.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/feature.hpp>

// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_gray.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"

namespace mapnik {

namespace detail {

template <typename F>
struct image_data_dispatcher :  util::static_visitor<void>
{
    using composite_function = F;
    image_data_dispatcher(int start_x, int start_y,
                          int width, int height,
                          double scale_x, double scale_y,
                          scaling_method_e method, double filter_factor,
                          double opacity, composite_mode_e comp_op,
                          raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional<double> const& nodata)
        : start_x_(start_x),
          start_y_(start_y),
          width_(width),
          height_(height),
          scale_x_(scale_x),
          scale_y_(scale_y),
          method_(method),
          filter_factor_(filter_factor),
        opacity_(opacity),
        comp_op_(comp_op),
        sym_(sym),
        feature_(feature),
        composite_(composite),
        nodata_(nodata) {}

    void operator() (image_data_null const& data_in) const {}  //no-op
    void operator() (image_data_rgba8 const& data_in) const
    {
        image_data_rgba8 data_out(width_, height_);
        scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
        composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
    }

    template <typename T>
    void operator() (T const& data_in) const
    {
        using image_data_type = T;
        image_data_type data_out(width_, height_);
        scale_image_agg(data_out, data_in,  method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_);
        image_data_rgba8 dst(width_, height_);
        raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
        if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
        composite_(dst, comp_op_, opacity_, start_x_, start_y_);
    }
private:
    int start_x_;
    int start_y_;
    int width_;
    int height_;
    double scale_x_;
    double scale_y_;
    scaling_method_e method_;
    double filter_factor_;
    double opacity_;
    composite_mode_e comp_op_;
    raster_symbolizer const& sym_;
    feature_impl const& feature_;
    composite_function & composite_;
    boost::optional<double> const& nodata_;
};

template <typename F>
struct image_data_warp_dispatcher :  util::static_visitor<void>
{
    using composite_function = F;
    image_data_warp_dispatcher(proj_transform const& prj_trans,
                               int start_x, int start_y, int width, int height,
                               box2d<double> const& target_ext, box2d<double> const& source_ext,
                               double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method,
                               double filter_factor, double opacity, composite_mode_e comp_op,
                               raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional<double> const& nodata)
        : prj_trans_(prj_trans),
        start_x_(start_x),
        start_y_(start_y),
        width_(width),
        height_(height),
        target_ext_(target_ext),
        source_ext_(source_ext),
        offset_x_(offset_x),
        offset_y_(offset_y),
        mesh_size_(mesh_size),
        scaling_method_(scaling_method),
        filter_factor_(filter_factor),
        opacity_(opacity),
        comp_op_(comp_op),
        sym_(sym),
        feature_(feature),
        composite_(composite),
        nodata_(nodata) {}

    void operator() (image_data_null const& data_in) const {} //no-op

    void operator() (image_data_rgba8 const& data_in) const
    {
        image_data_rgba8 data_out(width_, height_);
        if (nodata_) data_out.set(*nodata_);
        warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
        composite_(data_out, comp_op_, opacity_, start_x_, start_y_);
    }

    template <typename T>
    void operator() (T const& data_in) const
    {
        using image_data_type = T;
        image_data_type data_out(width_, height_);
        if (nodata_) data_out.set(*nodata_);
        warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_);
        image_data_rgba8 dst(width_, height_);
        raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym_, keys::colorizer);
        if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_);
        composite_(dst, comp_op_, opacity_, start_x_, start_y_);
    }
private:
    proj_transform const& prj_trans_;
    int start_x_;
    int start_y_;
    int width_;
    int height_;
    box2d<double> const& target_ext_;
    box2d<double> const& source_ext_;
    double offset_x_;
    double offset_y_;
    unsigned mesh_size_;
    scaling_method_e scaling_method_;
    double filter_factor_;
    double opacity_;
    composite_mode_e comp_op_;
    raster_symbolizer const& sym_;
    feature_impl const& feature_;
    composite_function & composite_;
    boost::optional<double> const& nodata_;
};

}

template <typename F>
void render_raster_symbolizer(raster_symbolizer const& sym,
                              mapnik::feature_impl& feature,
                              proj_transform const& prj_trans,
                              renderer_common& common,
                              F composite)
{
    raster_ptr const& source = feature.get_raster();
    if (source)
    {
        box2d<double> target_ext = box2d<double>(source->ext_);
        prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
        box2d<double> ext = common.t_.forward(target_ext);
        int start_x = static_cast<int>(std::floor(ext.minx()+.5));
        int start_y = static_cast<int>(std::floor(ext.miny()+.5));
        int end_x = static_cast<int>(std::floor(ext.maxx()+.5));
        int end_y = static_cast<int>(std::floor(ext.maxy()+.5));
        int raster_width = end_x - start_x;
        int raster_height = end_y - start_y;
        if (raster_width > 0 && raster_height > 0)
        {
            scaling_method_e scaling_method = get<scaling_method_e>(sym, keys::scaling, feature, common.vars_, SCALING_NEAR);
            composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, common.vars_, src_over);
            double opacity = get<double>(sym,keys::opacity,feature, common.vars_, 1.0);
            bool premultiply_source = !source->premultiplied_alpha_;
            auto is_premultiplied = get_optional<bool>(sym, keys::premultiplied, feature, common.vars_);
            if (is_premultiplied)
            {
                if (*is_premultiplied) premultiply_source = false;
                else premultiply_source = true;
            }
            // only premuiltiply rgba8 images
            if (premultiply_source && source->data_.is<image_data_rgba8>())
            {
                agg::rendering_buffer buffer(source->data_.getBytes(),
                                             source->data_.width(),
                                             source->data_.height(),
                                             source->data_.width() * 4);
                agg::pixfmt_rgba32 pixf(buffer);
                pixf.premultiply();
            }

            if (!prj_trans.equal())
            {
                double offset_x = ext.minx() - start_x;
                double offset_y = ext.miny() - start_y;
                unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, common.vars_, 16));
                detail::image_data_warp_dispatcher<F> dispatcher(prj_trans, start_x, start_y, raster_width, raster_height,
                                                                 target_ext, source->ext_, offset_x, offset_y, mesh_size,
                                                                 scaling_method, source->get_filter_factor(),
                                                                 opacity, comp_op, sym, feature, composite, source->nodata());
                util::apply_visitor(dispatcher, source->data_);
            }
            else
            {
                double image_ratio_x = ext.width() / source->data_.width();
                double image_ratio_y = ext.height() / source->data_.height();
                double eps = 1e-5;
                if ( (std::fabs(image_ratio_x - 1.0) <= eps) &&
                     (std::fabs(image_ratio_y - 1.0) <= eps) &&
                     (std::abs(start_x) <= eps) &&
                     (std::abs(start_y) <= eps) )
                {
                    if (source->data_.is<image_data_rgba8>())
                    {
                        composite(util::get<image_data_rgba8>(source->data_), comp_op, opacity, start_x, start_y);
                    }
                }
                else
                {
                    detail::image_data_dispatcher<F> dispatcher(start_x, start_y, raster_width, raster_height,
                                                                image_ratio_x, image_ratio_y,
                                                                scaling_method, source->get_filter_factor(),
                                                                opacity, comp_op, sym, feature, composite, source->nodata());
                    util::apply_visitor(dispatcher, source->data_);
                }
            }
        }
    }
}

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________
// Implementation version v0 of EMCAL Manager class
// An object of this class does not produce hits nor digits
// It is the one to use if you do not want to produce outputs in TREEH or TREED
// This class places a Geometry of the EMCAL in the ALICE Detector as defined in AliEMCALGeometry.cxx
//*-- Author: Yves Schutz (SUBATECH)
//*-- and   : Sahal Yacoob (LBL / UCT)

// This Version of AliEMCALv0 reduces the number of volumes placed in XEN1 (the envelope) to less than five hundred
// The Envelope is Placed in Alice, And the Aluminium layer. Mini envelopes (XU) are then placed in XEN1.
// Each mini envelope contains 2 scintillator, and 2 lead layers, except the last one which contains just one scintillator layer.
// At the moment I cannot place the 36 and above layers in the mini envelopes so all layers are still placed in XEN1

// --- ROOT system ---
#include "TPGON.h"
#include "TTUBS.h"
#include "TNode.h"
#include "TRandom.h"
#include "TGeometry.h"
//#include "Tstring.h"

// --- Standard library ---

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strstream.h>
#include <iostream.h>

// --- AliRoot header files ---

#include "AliEMCALv0.h"
#include "AliEMCALGeometry.h"
#include "AliConst.h"
#include "AliRun.h"
#include "AliMC.h"

ClassImp(AliEMCALv0)

//______________________________________________________________________
AliEMCALv0::AliEMCALv0(const char *name, const char *title):
    AliEMCAL(name,title){
    // Standard Constructor

    if (strcmp(GetTitle(),"") != 0 )
	fGeom =  AliEMCALGeometry::GetInstance(GetTitle(), "") ;

}
//______________________________________________________________________
void AliEMCALv0::BuildGeometry(){
    // Display Geometry for display.C

    const Int_t kColorArm1   = kBlue ;

    // Difine the shape of the Calorimeter

    new TTUBS("Envelop1", "Tubs that contains arm 1", "void",
	      fGeom->GetEnvelop(0),     // rmin
	      fGeom->GetEnvelop(1) +30 ,     // rmax
	      fGeom->GetEnvelop(2)/2.0, // half length in Z
	      fGeom->GetArm1PhiMin(),   // minimun phi angle
	      fGeom->GetArm1PhiMax()    // maximun phi angle
	);
    // Place the Node
    TNode * envelop1node = new TNode("Envelop1", "Arm1 Envelop", "Envelop1") ;
    envelop1node->SetLineColor(kColorArm1) ;
    fNodes->Add(envelop1node) ;
}
//______________________________________________________________________
void AliEMCALv0::CreateGeometry(){
    // Create the EMCAL geometry for Geant

    AliEMCALv0 *emcaltmp = (AliEMCALv0*)gAlice->GetModule("EMCAL") ;

    if ( emcaltmp == NULL ) {
	Warning("CreateGeometry","detector not found!");
	return;
    } // end if
    // Get pointer to the array containing media indices
    Int_t *idtmed = fIdtmed->GetArray() - 1599 ;

    // Create an Envelope within which to place the Detector

    Float_t envelopA[5]  ;
      envelopA[0] = fGeom->GetEnvelop(0) ;         // rmin
      envelopA[1] = fGeom->GetEnvelop(1) + 30 ;    // rmax
      envelopA[2] = fGeom->GetEnvelop(2) / 2.0 ;   // dz
      envelopA[3] = fGeom->GetArm1PhiMin() ;       // minimun phi angle
      envelopA[4] = fGeom->GetArm1PhiMax() ;       // maximun phi angle

     // create XEN1
    gMC->Gsvolu("XEN1", "TUBS ", idtmed[1599], envelopA, 5) ; //filled with air

    Int_t idrotm = 1;
    AliMatrix(idrotm, 90.0, 0., 90.0, 90.0, 0.0, 0.0) ;

    // Position the Envelope in Alice
    gMC->Gspos("XEN1", 1, "ALIC", 0.0, 0.0, 0.0, idrotm, "ONLY") ;
     envelopA[1]  =envelopA[0] + fGeom->GetGap2Active();
    TString label = "XU0";

         envelopA[0] = envelopA[1]+ 3.18 ; //rmin Start mini envelopes after the aluminium layer
	envelopA[1] = envelopA[0] + 2.2    ;  //rmax larger for first two layers (preshower)

    gMC->Gsvolu(label.Data(), "TUBS ", idtmed[1599], envelopA, 5) ; //filled with air
    gMC->Gspos(label.Data(), 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY") ; // Place XU0 in to XEN1

 for (int i = 1; i < ((fGeom->GetNLayers()-1)/2) + 1 ; i++ ){
       label = "XU" ;
       label += i ;

       envelopA[0] = envelopA[1] ; //rmin
       envelopA[1] = envelopA[0] + 2.0  ;  //rmax

    gMC->Gsvolu(label.Data(), "TUBS ", idtmed[1599], envelopA, 5) ; //filled with air
    gMC->Gspos(label.Data(), 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

	} // end  i

    // Create the shapes of active material (LEAD/Aluminium/Scintillator) to be placed

    Float_t envelopB[10]; // First Layer of Aluminium
    Float_t envelopC[10]; // Scintillator Layers
    Float_t envelopD[10]; //  Lead Layers

    envelopC[0] = envelopD[0] =  envelopB[0] = fGeom->GetArm1PhiMin(); //starting position in Phi
    envelopC[1] = envelopD[1] =  envelopB[1] = fGeom->GetArm1PhiMax() -  // Angular size of the Detector in Phi
	                                       fGeom->GetArm1PhiMin();
    envelopC[2] = envelopD[2] =  envelopB[2] = fGeom->GetNPhi() ; // Number of Section in Phi
    envelopD[3] = envelopC[3] = envelopB[3] = 2; // each section will be passed 2 z coordinates

    envelopB[4] = (fGeom->GetEnvelop(0) + fGeom->GetGap2Active()) /
                  (tan(2*atan(exp(0.7)))) ;                          // z co-ordinate 1
    envelopB[5] = fGeom->GetEnvelop(0) + fGeom->GetGap2Active(); //rmin at z1
    envelopD[6] = envelopB[6] = envelopB[5] + 3.18;  //rmax at z1
    envelopB[7] = (fGeom->GetEnvelop(0) + fGeom->GetGap2Active()) /
	          (tan(2*atan(exp(-0.7)))) ;              // z co-ordinate 2
    envelopB[8] = envelopB[5] ; //
    envelopB[9] = envelopB[6] ; // radii are the same.

    // filled shapes wit hactive material
    gMC->Gsvolu("XALU", "PGON", idtmed[1602], envelopB, 10); // Define Aluminium volume completely
    gMC->Gsvolu("XPST", "PGON", idtmed[1601], 0, 0) ;  // The polystyrene layers will be defined when placed
    gMC->Gsvolu("XPBX", "PGON", idtmed[1600], 0, 0) ; //  as will the lead layers
    gMC->Gsdvn("XPHI", "XPST", fGeom->GetNPhi(), 2) ; //  Dividind eta polystyrene divisions into phi segments.

    // Position Aluminium Layer in the Envelope
    gMC->Gspos("XALU", 1, "XEN1", 0.0, 0.0, 0.0 , idrotm, "ONLY") ;

// The loop below places the scintillator in Lead Layers alternately.

    for (int i = 0; i < fGeom->GetNLayers() ; i++ ){

       label = "XU" ;

        label += (int) i/2  ; // we will place two layers (i = one layer) in each mini envelope)
        envelopC[5] = envelopD[6] ; //rmin
	envelopC[6] = envelopD[6] + ((i > 1)  ? 0.5 : 0.6)  ;  //rmax larger for first two layers (preshower)
	envelopC[8] = envelopD[6] ; //rmin
	envelopC[9] = envelopD[6] + ((i > 1 ) ? 0.5 : 0.6)  ;  //rmax larger for first two layers (preshower)
	for (int j =0; j < (fGeom->GetNZ()) ; j++){
	    envelopC[4] = envelopD[6]/tan(2*atan(exp(0.7-(j*1.4/
                                                      (fGeom->GetNZ()))))); //z begin
	    envelopC[7] = envelopD[6]/tan(2*atan(exp(0.7-((j+1)*1.4/
                                                      (fGeom->GetNZ()))))); // z end
	    gMC->Gsposp("XPST",1+j+i*(fGeom->GetNZ()), label.Data(), // should be used but there's a weird crash above i = 18,
			0.0, 0.0, 0.0 , idrotm, "ONLY", envelopC, 10); // Position and define layer
	} // end for j
	if (i < (fGeom->GetNLayers()-1)){

             envelopD[5] = envelopC[6] ; //rmin
	    envelopD[6] = envelopC[6] + 0.5;  //rmax
	    envelopD[8] = envelopC[6] ; //rmin
	    envelopD[9] = envelopC[6] + 0.5;  //rmax
	    for (int j =0; j < (fGeom->GetNZ()) ; j++){
		envelopD[4] = envelopC[6]/tan(2*atan(exp(0.7-(j*1.4/
                                                       (fGeom->GetNZ()))))); // z begin
		envelopD[7] = envelopC[6]/tan(2*atan(exp(0.7-((j+1)*1.4/
                                                        (fGeom->GetNZ()))))); // z end
		gMC->Gsposp("XPBX",1+ j+i*(fGeom->GetNZ()), label.Data(),
			    0.0, 0.0, 0.0 , idrotm, "ONLY", envelopD, 10) ; // Position and Define Layer
	    } // end for j
	} // end if i
    }  // for i
}
//______________________________________________________________________
void AliEMCALv0::Init(void){
    // Just prints an information message
    Int_t i;

    cout << endl;
    for(i=0;i<35;i++) cout <<"*";
    cout << " EMCAL_INIT ";
    for(i=0;i<35;i++) cout << "*";
    cout << endl;

    // Here the EMCAL initialisation code (if any!)

    if (fGeom!=0)
	cout << "AliEMCAL" << Version() << " : EMCAL geometry intialized for "
	     << fGeom->GetName() << endl ;
    else
	cout << "AliEMCAL" << Version() <<
	    " : EMCAL geometry initialization failed !" << endl ;
    for(i=0;i<80;i++) printf("*");
    cout << endl;
}
<commit_msg>Cleaned CreateGeometry<commit_after>/**************************************************************************

 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *

 *                                                                        *

 * Author: The ALICE Off-line Project.                                    *

 * Contributors are mentioned in the code where appropriate.              *

 *                                                                        *

 * Permission to use, copy, modify and distribute this software and its   *

 * documentation strictly for non-commercial purposes is hereby granted   *

 * without fee, provided that the above copyright notice appears in all   *

 * copies and that both the copyright notice and this permission notice   *

 * appear in the supporting documentation. The authors make no claims     *

 * about the suitability of this software for any purpose. It is          *

 * provided "as is" without express or implied warranty.                  *

 **************************************************************************/

/* $Id$ */

//_________________________________________________________________________

// Implementation version v0 of EMCAL Manager class

// An object of this class does not produce hits nor digits

// It is the one to use if you do not want to produce outputs in TREEH or TREED

// This class places a Geometry of the EMCAL in the ALICE Detector as defined in AliEMCALGeometry.cxx

//*-- Author: Yves Schutz (SUBATECH)

//*-- and   : Sahal Yacoob (LBL / UCT)

// This Version of AliEMCALv0 reduces the number of volumes placed in XEN1 (the envelope) to less than five hundred

// The Envelope is Placed in Alice, And the Aluminium layer. Mini envelopes (XU) are then placed in XEN1.

// Each mini envelope contains 2 scintillator, and 2 lead layers, except the last one which contains just one scintillator layer.

// At the moment I cannot place the 36 and above layers in the mini envelopes so all layers are still placed in XEN1

// --- ROOT system ---

#include "TPGON.h"

#include "TTUBS.h"

#include "TNode.h"

#include "TRandom.h"

#include "TGeometry.h"

//#include "Tstring.h"

// --- Standard library ---

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <strstream.h>

#include <iostream.h>

// --- AliRoot header files ---

#include "AliEMCALv0.h"

#include "AliEMCALGeometry.h"

#include "AliConst.h"

#include "AliRun.h"

#include "AliMC.h"

ClassImp(AliEMCALv0)

//______________________________________________________________________

AliEMCALv0::AliEMCALv0(const char *name, const char *title):

    AliEMCAL(name,title){

    // Standard Constructor

    if (strcmp(GetTitle(),"") != 0 )

	fGeom =  AliEMCALGeometry::GetInstance(GetTitle(), "") ;

}

//______________________________________________________________________

void AliEMCALv0::BuildGeometry(){

    // Display Geometry for display.C

    const Int_t kColorArm1   = kBlue ;

    // Difine the shape of the Calorimeter

    new TTUBS("Envelop1", "Tubs that contains arm 1", "void",

	      fGeom->GetEnvelop(0),     // rmin

	      fGeom->GetEnvelop(1) +30 ,     // rmax

	      fGeom->GetEnvelop(2)/2.0, // half length in Z

	      fGeom->GetArm1PhiMin(),   // minimun phi angle

	      fGeom->GetArm1PhiMax()    // maximun phi angle

	);

    // Place the Node

    TNode * envelop1node = new TNode("Envelop1", "Arm1 Envelop", "Envelop1") ;

    envelop1node->SetLineColor(kColorArm1) ;

    fNodes->Add(envelop1node) ;

}

//______________________________________________________________________

void AliEMCALv0::CreateGeometry(){

    // Create the EMCAL geometry for Geant

    Float_t etamin,etamax;

    if(fGeom->IsInitialized()){

	Error("CreateGeometry","EMCAL Geometry class has not been set up.");

    } // end if

    // Get pointer to the array containing media indices

    Int_t *idtmed = fIdtmed->GetArray() - 1599 ;

    // Create an Envelope within which to place the Detector

    Float_t envelopA[5];

    envelopA[0] = fGeom->GetEnvelop(0);     // rmin

    envelopA[1] = fGeom->GetEnvelop(1);     // rmax

    envelopA[2] = fGeom->GetEnvelop(2)/2.0; // dz

    envelopA[3] = fGeom->GetArm1PhiMin();   // minimun phi angle

    envelopA[4] = fGeom->GetArm1PhiMax();   // maximun phi angle

    // create XEN1

    gMC->Gsvolu("XEN1", "TUBS ", idtmed[1599], envelopA, 5) ; //filled with air

    Int_t idrotm = 1;

    AliMatrix(idrotm, 90.0, 0., 90.0, 90.0, 0.0, 0.0) ;

    // Position the EMCAL Mother Volume in Alice

    gMC->Gspos("XEN1", 1, "ALIC", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

    //

    TString label = "XU0";

    //rmin Start mini envelopes after the aluminium layer

    envelopA[0] = fGeom->GetEnvelop(0) + fGeom->GetGap2Active() +

	          fGeom->GetAlFrontThickness();

    //rmax larger for first two layers (preshower);

    Float_t tseg = fGeom->GetPreSintThick()+fGeom->GetPbRadThick();

    envelopA[1] = envelopA[0] + 2.0*tseg;

    envelopA[2] = fGeom->GetEnvelop(2)/2.0; // dz

    envelopA[3] = fGeom->GetArm1PhiMin();   // minimun phi angle

    envelopA[4] = fGeom->GetArm1PhiMax();   // maximun phi angle

    //filled with air

    gMC->Gsvolu(label.Data(), "TUBS ", idtmed[1599], envelopA, 5);

    // Place XU0 in to XEN1

    gMC->Gspos(label.Data(), 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY");

    tseg = fGeom->GetFullSintThick()+fGeom->GetPbRadThick();

    for (int i = 1; i < ((fGeom->GetNLayers()-1)/2) + 1 ; i++ ){

	label = "XU" ;

	label += i ;

	envelopA[0] = envelopA[1]; //rmin

	envelopA[1] = envelopA[0] + 2.0*tseg;  //rmax

	 //filled with air

	gMC->Gsvolu(label.Data(), "TUBS ", idtmed[1599], envelopA, 5);

	gMC->Gspos(label.Data(), 1, "XEN1", 0.0, 0.0, 0.0, idrotm, "ONLY") ;

    } // end  i

    // Create the shapes of active material (LEAD/Aluminium/Scintillator)

    // to be placed

    Float_t envelopB[10]; // First Layer of Aluminium

    Float_t envelopC[10]; // Scintillator Layers

    Float_t envelopD[10]; // Lead Layers

    //starting position in Phi

    envelopC[0] = envelopD[0] =  envelopB[0] = fGeom->GetArm1PhiMin();

    // Angular size of the Detector in Phi

    envelopB[1] = fGeom->GetArm1PhiMax() - fGeom->GetArm1PhiMin();

    envelopC[1] = envelopD[1] = envelopB[1];

    // Number of Section in Phi

    envelopC[2] = envelopD[2] = envelopB[2] = fGeom->GetNPhi();

    // each section will be passed 2 z coordinates

    envelopD[3] = envelopC[3] = envelopB[3] = 2;

    envelopB[4] = fGeom->ZFromEtaR(fGeom->GetEnvelop(0)+fGeom->GetGap2Active(),

				   fGeom->GetArm1EtaMin());// z co-ordinate 1

    envelopB[5] = fGeom->GetEnvelop(0) + fGeom->GetGap2Active(); //rmin at z1

    envelopB[6] = envelopB[5] + fGeom->GetAlFrontThickness();//rmax at z1

    envelopD[6] = envelopB[6];

    envelopB[7] =fGeom->ZFromEtaR(fGeom->GetEnvelop(0)+fGeom->GetGap2Active(),

				  fGeom->GetArm1EtaMax()); // z co-ordinate 2

    envelopB[8] = envelopB[5] ; //

    envelopB[9] = envelopB[6] ; // radii are the same.

    // filled shapes wit hactive material

    // Define Aluminium volume completely

    gMC->Gsvolu("XALU", "PGON", idtmed[1602], envelopB, 10);

    // The polystyrene layers will be defined when placed

    gMC->Gsvolu("XPST", "PGON", idtmed[1601], 0, 0);

    gMC->Gsvolu("XPBX", "PGON", idtmed[1600], 0, 0);//  as will the lead layers

    //  Dividind eta polystyrene divisions into phi segments.

    gMC->Gsdvn("XPHI", "XPST", fGeom->GetNPhi(), 2);

    // Position Aluminium Layer in the Envelope

    gMC->Gspos("XALU", 1, "XEN1", 0.0, 0.0, 0.0 , idrotm, "ONLY") ;

    // The loop below places the scintillator in Lead Layers alternately.

    for (int i = 0; i < fGeom->GetNLayers() ; i++ ){

	label = "XU" ;

        label += (int) i/2  ; // we will place two layers (i = one layer) in each mini envelope)

        envelopC[5] = envelopD[6] ; //rmin

	envelopC[6] = envelopD[6] + ((i > 1)  ? fGeom->GetFullSintThick() :

				     fGeom->GetPreSintThick());//rmax larger for first two layers (preshower)

	envelopC[8] = envelopD[6] ; //rmin

	envelopC[9] = envelopD[6] + ((i > 1 ) ? fGeom->GetFullSintThick() :

				     fGeom->GetPreSintThick());//rmax larger for first two layers (preshower)

	for (int j =0; j < (fGeom->GetNEta()) ; j++){

	    etamin = fGeom->GetArm1EtaMin()+

		(j*fGeom->GetDeltaEta()/(fGeom->GetNEta()));

	    etamax = fGeom->GetArm1EtaMin()+

		((j+1)*fGeom->GetDeltaEta()/(fGeom->GetNEta()));

	    envelopC[4] = fGeom->ZFromEtaR(envelopD[6],etamin); //z begin

	    envelopC[7] = fGeom->ZFromEtaR(envelopD[6],etamax);// z end

	    gMC->Gsposp("XPST",1+j+i*(fGeom->GetNEta()), label.Data(), // should be used but there's a weird crash above i = 18,

			0.0, 0.0, 0.0 , idrotm, "ONLY", envelopC, 10); // Position and define layer

	} // end for j

	if (i < (fGeom->GetNLayers()-1)){

	    envelopD[5] = envelopC[6] ; //rmin

	    envelopD[6] = envelopC[6] + fGeom->GetPbRadThick();  //rmax

	    envelopD[8] = envelopC[6] ; //rmin

	    envelopD[9] = envelopC[6] + fGeom->GetPbRadThick();  //rmax

	    for (int j =0; j < (fGeom->GetNEta()) ; j++){

		etamin = fGeom->GetArm1EtaMin()+

		    (j*fGeom->GetDeltaEta()/(fGeom->GetNEta()));

		etamax = fGeom->GetArm1EtaMin()+

		    ((j+1)*fGeom->GetDeltaEta()/(fGeom->GetNEta()));

		envelopD[4] = fGeom->ZFromEtaR(envelopC[6],etamin);//z begin

		envelopD[7] = fGeom->ZFromEtaR(envelopC[6],etamax);// z end

		// Position and Define Layer

		gMC->Gsposp("XPBX",1+ j+i*(fGeom->GetNEta()), label.Data(),

			    0.0, 0.0, 0.0 , idrotm, "ONLY", envelopD, 10);

	    } // end for j

	} // end if i

    }  // for i

}

//______________________________________________________________________

void AliEMCALv0::Init(void){

    // Just prints an information message

    Int_t i;

    cout << endl;

    for(i=0;i<35;i++) cout <<"*";

    cout << " EMCAL_INIT ";

    for(i=0;i<35;i++) cout << "*";

    cout << endl;

    // Here the EMCAL initialisation code (if any!)

    if (fGeom!=0)

	cout << "AliEMCAL" << Version() << " : EMCAL geometry intialized for "

	     << fGeom->GetName() << endl ;

    else

	cout << "AliEMCAL" << Version() <<

	    " : EMCAL geometry initialization failed !" << endl ;

    for(i=0;i<80;i++) printf("*");

    cout << endl;

}

<|endoftext|>


<commit_before>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <chrono>
#include <algorithm>
#include "sensorset.hpp"
#include "hwmon.hpp"
#include "sysfs.hpp"
#include "mainloop.hpp"
#include "util.hpp"
#include "env.hpp"

using namespace std::literals::chrono_literals;

static constexpr auto typeAttrMap =
{
    // 1 - hwmon class
    // 2 - unit
    // 3 - sysfs scaling factor
    std::make_tuple(
        hwmon::type::ctemp,
        ValueInterface::Unit::DegreesC,
        -3),
    std::make_tuple(
        hwmon::type::cfan,
        ValueInterface::Unit::RPMS,
        0),
    std::make_tuple(
        hwmon::type::cvolt,
        ValueInterface::Unit::Volts,
        -3),
};

auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<0>(attrs);
}

auto getUnit(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<1>(attrs);
}

auto getScale(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<2>(attrs);
}

MainLoop::MainLoop(
    sdbusplus::bus::bus&& bus,
    const std::string& path,
    const char* prefix,
    const char* root)
    : _bus(std::move(bus)),
      _manager(sdbusplus::server::manager::manager(_bus, root)),
      _shutdown(false),
      _path(path),
      _prefix(prefix),
      _root(root),
      state()
{
    if (_path.back() == '/')
    {
        _path.pop_back();
    }
}

void MainLoop::shutdown() noexcept
{
    _shutdown = true;
}

void MainLoop::run()
{
    // Check sysfs for available sensors.
    auto sensors = std::make_unique<SensorSet>(_path);

    for (auto& i : *sensors)
    {
        // Get sensor configuration from the environment.

        // Ignore inputs without a label.
        auto label = getEnv("LABEL", i.first);
        if (label.empty())
        {
            continue;
        }

        // Get the initial value for the value interface.
        auto sysfsPath = make_sysfs_path(
                             _path,
                             i.first.first,
                             i.first.second,
                             hwmon::entry::input);
        int val = 0;
        read_sysfs(sysfsPath, val);

        std::string objectPath{_root};
        objectPath.append("/");
        objectPath.append(i.first.first);
        objectPath.append("/");
        objectPath.append(label);

        ObjectInfo info(&_bus, std::move(objectPath), Object());
        auto& o = std::get<Object>(info);

        auto iface = std::make_shared<ValueObject>(_bus, objectPath.c_str());
        iface->value(val);

        const auto& attrs = std::find_if(
                                typeAttrMap.begin(),
                                typeAttrMap.end(),
                                [&](const auto & e)
        {
            return i.first.first == getHwmonType(e);
        });
        if (attrs != typeAttrMap.end())
        {
            iface->unit(getUnit(*attrs));
            iface->scale(getScale(*attrs));
        }

        o.emplace(InterfaceType::VALUE, iface);

        auto value = std::make_tuple(
                         std::move(i.second),
                         std::move(label),
                         std::move(info));

        state[std::move(i.first)] = std::move(value);
    }

    {
        auto copy = std::unique_ptr<char, phosphor::utility::Free<char>>(strdup(
                        _path.c_str()));
        auto busname = std::string(_prefix) + '.' + basename(copy.get());
        _bus.request_name(busname.c_str());
    }

    // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
    //       ensure the objects all exist?

    // Polling loop.
    while (!_shutdown)
    {
        // Iterate through all the sensors.
        for (auto& i : state)
        {
            auto& attrs = std::get<0>(i.second);
            if (attrs.find(hwmon::entry::input) != attrs.end())
            {
                // Read value from sensor.
                int value = 0;
                read_sysfs(make_sysfs_path(_path,
                                           i.first.first, i.first.second,
                                           hwmon::entry::input),
                           value);

                auto& objInfo = std::get<ObjectInfo>(i.second);
                auto& obj = std::get<Object>(objInfo);
                auto iface = obj.find(InterfaceType::VALUE);

                if (iface != obj.end())
                {
                    auto realIface = std::experimental::any_cast<std::shared_ptr<ValueObject>>
                                     (iface->second);
                    realIface->value(value);
                }
            }
        }

        // Respond to DBus
        _bus.process_discard();

        // Sleep until next interval.
        // TODO: Issue#5 - Make this configurable.
        // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
        _bus.wait((1000000us).count());

        // TODO: Issue#7 - Should probably periodically check the SensorSet
        //       for new entries.
    }
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>Move value interface creation to a helper method.<commit_after>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <iostream>
#include <memory>
#include <cstring>
#include <cstdlib>
#include <chrono>
#include <algorithm>
#include "sensorset.hpp"
#include "hwmon.hpp"
#include "sysfs.hpp"
#include "mainloop.hpp"
#include "util.hpp"
#include "env.hpp"

using namespace std::literals::chrono_literals;

static constexpr auto typeAttrMap =
{
    // 1 - hwmon class
    // 2 - unit
    // 3 - sysfs scaling factor
    std::make_tuple(
        hwmon::type::ctemp,
        ValueInterface::Unit::DegreesC,
        -3),
    std::make_tuple(
        hwmon::type::cfan,
        ValueInterface::Unit::RPMS,
        0),
    std::make_tuple(
        hwmon::type::cvolt,
        ValueInterface::Unit::Volts,
        -3),
};

auto getHwmonType(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<0>(attrs);
}

auto getUnit(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<1>(attrs);
}

auto getScale(decltype(typeAttrMap)::const_reference attrs)
{
    return std::get<2>(attrs);
}

auto addValue(const SensorSet::key_type& sensor,
              const std::string& sysfsRoot, ObjectInfo& info)
{
    // Get the initial value for the value interface.
    auto& bus = *std::get<sdbusplus::bus::bus*>(info);
    auto& obj = std::get<Object>(info);
    auto& objPath = std::get<std::string>(info);

    auto sysfsPath = make_sysfs_path(
                         sysfsRoot,
                         sensor.first,
                         sensor.second,
                         hwmon::entry::input);
    int val = 0;
    read_sysfs(sysfsPath, val);

    auto iface = std::make_shared<ValueObject>(bus, objPath.c_str());
    iface->value(val);

    // *INDENT-OFF*
    const auto& attrs = std::find_if(
                            typeAttrMap.begin(),
                            typeAttrMap.end(),
                            [&](const auto & e)
                            {
                                return sensor.first == getHwmonType(e);
                            });
    // *INDENT-ON*

    if (attrs != typeAttrMap.end())
    {
        iface->unit(getUnit(*attrs));
        iface->scale(getScale(*attrs));
    }

    obj[InterfaceType::VALUE] = iface;
    return iface;
}

MainLoop::MainLoop(
    sdbusplus::bus::bus&& bus,
    const std::string& path,
    const char* prefix,
    const char* root)
    : _bus(std::move(bus)),
      _manager(sdbusplus::server::manager::manager(_bus, root)),
      _shutdown(false),
      _path(path),
      _prefix(prefix),
      _root(root),
      state()
{
    if (_path.back() == '/')
    {
        _path.pop_back();
    }
}

void MainLoop::shutdown() noexcept
{
    _shutdown = true;
}

void MainLoop::run()
{
    // Check sysfs for available sensors.
    auto sensors = std::make_unique<SensorSet>(_path);

    for (auto& i : *sensors)
    {
        // Get sensor configuration from the environment.

        // Ignore inputs without a label.
        auto label = getEnv("LABEL", i.first);
        if (label.empty())
        {
            continue;
        }

        std::string objectPath{_root};
        objectPath.append("/");
        objectPath.append(i.first.first);
        objectPath.append("/");
        objectPath.append(label);

        ObjectInfo info(&_bus, std::move(objectPath), Object());
        auto valueInterface = addValue(i.first, _path, info);

        auto value = std::make_tuple(
                         std::move(i.second),
                         std::move(label),
                         std::move(info));

        state[std::move(i.first)] = std::move(value);
    }

    {
        auto copy = std::unique_ptr<char, phosphor::utility::Free<char>>(strdup(
                        _path.c_str()));
        auto busname = std::string(_prefix) + '.' + basename(copy.get());
        _bus.request_name(busname.c_str());
    }

    // TODO: Issue#3 - Need to make calls to the dbus sensor cache here to
    //       ensure the objects all exist?

    // Polling loop.
    while (!_shutdown)
    {
        // Iterate through all the sensors.
        for (auto& i : state)
        {
            auto& attrs = std::get<0>(i.second);
            if (attrs.find(hwmon::entry::input) != attrs.end())
            {
                // Read value from sensor.
                int value = 0;
                read_sysfs(make_sysfs_path(_path,
                                           i.first.first, i.first.second,
                                           hwmon::entry::input),
                           value);

                auto& objInfo = std::get<ObjectInfo>(i.second);
                auto& obj = std::get<Object>(objInfo);
                auto iface = obj.find(InterfaceType::VALUE);

                if (iface != obj.end())
                {
                    auto realIface = std::experimental::any_cast<std::shared_ptr<ValueObject>>
                                     (iface->second);
                    realIface->value(value);
                }
            }
        }

        // Respond to DBus
        _bus.process_discard();

        // Sleep until next interval.
        // TODO: Issue#5 - Make this configurable.
        // TODO: Issue#6 - Optionally look at polling interval sysfs entry.
        _bus.wait((1000000us).count());

        // TODO: Issue#7 - Should probably periodically check the SensorSet
        //       for new entries.
    }
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <fstream>
#include <vector>
#include <string>
#include <type_traits>
#include <iomanip>

#include "cmdline/cmdline.h"
#include "picojson/picojson.h"
#include "sais/sais.hxx"
#include "wavelet_matrix.h"

using namespace std;

typedef int64_t index_type;
#define iter(c) decltype((c).size())

vector<uint8_t> bwt(const vector<uint8_t> &S) {
  vector<uint8_t> T(S.size());
  vector<index_type> tmp(S.size());

  vector<uint8_t> &S2 = const_cast<vector<uint8_t> &>(S);

  saisxx_bwt(S2.begin(), T.begin(), tmp.begin(), (index_type)S.size());

  return T;
}

vector<uint8_t> ibwt(const vector<uint8_t> &T, const index_type pid) {
  vector<uint64_t> C(256, 0);
  for (const auto &c : T) {
    ++C[c];
  }

  uint64_t sum = 0;
  for (iter(C) i = 0; i < C.size(); ++i) {
    uint64_t cur = C[i];
    C[i] = sum;
    sum += cur;
  }

  vector<index_type> phi(T.size());
  for (iter(T) i = 0; i < T.size(); ++i) {
    phi[C[T[i]]] = i;
    ++C[T[i]];
  }

  vector<uint8_t> S(T.size());
  index_type j = pid;
  for (iter(T) i = 0; i < T.size(); ++i) {
    S[i] = T[phi[j]];
    j = phi[j];
  }

  return S;
}

string read_oneline(const string &ifname) {
  ifstream ifs(ifname);

  if (!ifs) {
    perror(ifname.c_str());
    exit(EXIT_FAILURE);
  }

  string s;
  getline(ifs, s);
  return s;
}

void show_string_in_hex(const string &s) {
  for (iter(s) i = 0; i < s.size(); ++i) {
    if (i > 0)
      cout << ' ';
    unsigned char c = s[i];
    cerr << "0x" << hex << (int)c;
  }
  cerr << endl;
}

bool is_utf8_start_char(unsigned char c) {
  // 2バイト目以降は先頭ビットが10である
  if ((c >> 6) == 2)
    return false;
  return true;
}

pair<index_type, index_type> fm_index(const WaveletMatrix &wat,
                                      const string &p) {
  index_type sp = 0;
  index_type ep = wat.length();
  for (iter(p) i = 0; i < p.size(); ++i) {
    unsigned char c = p[p.size() - 1 - i];
    sp = wat.rank_lt(c) + wat.rank(c, sp);
    ep = wat.rank_lt(c) + wat.rank(c, ep);
    if (sp >= ep)
      return make_pair(-1, -1);
  }
  return make_pair(sp, ep);
}

vector<vector<string>> read_datasets(const string &cfname) {
  ifstream ifs(cfname);

  if (!ifs) {
    perror(cfname.c_str());
    exit(EXIT_FAILURE);
  }

  picojson::value json;
  string err = picojson::parse(json, ifs);

  if (!err.empty()) {
    cerr << err << endl;
    exit(EXIT_FAILURE);
  }

  picojson::array &array = json.get<picojson::array>();
  vector<vector<string>> ret;
  for (const picojson::value &it : array) {
    picojson::object book = it.get<picojson::object>();
    string filename = book["filename"].get<string>();
    string title = book["title"].get<string>();
    string author = book["author"].get<string>();
    vector<string> vs = { read_oneline(filename), title, author };
    ret.emplace_back(vs);
  }
  return ret;
}

void search(const string &query, const int num,
            const WaveletMatrix &wt_text,
            const WaveletMatrix &wt_freq,
            const vector<vector<string>> &datasets) {
  auto spep = fm_index(wt_text, query);
  vector<pair<WaveletMatrix::Index, int>> res = wt_freq.topk<int>(spep.first, spep.second, num);
  for (const auto &r : res) {
    if (r.second == datasets.size())
      continue;
    cout << r.first << '\t' << datasets[r.second][1] << '\t' << datasets[r.second][2]
         << endl;
  }
}

int main(int argc, char *argv[]) {
  cmdline::parser parser;
  parser.add<string>("config", 'c', "config json file", /* need = */ true);
  parser.add<string>("query", 'q', "query string", /* need = */ false);
  parser.add<int>("number", 'n', "display first `number` lines",
                  /* need = */ false, /* default = */ 20);
  parser.add("interact", 'i', "launch interactive shell");
  parser.add("help", 'h', "show help");

  if (!parser.parse(argc, argv) || parser.exist("help")) {
    cerr << parser.error_full() << parser.usage() << endl;
    exit(EXIT_FAILURE);
  }

  if (parser.exist("query") == false && parser.exist("interact") == false) {
    cerr << "you should enable --query or --interact" << endl;
    exit(EXIT_FAILURE);
  }

  string cfname = parser.get<string>("config");
  vector<vector<string>> datasets = read_datasets(cfname);

  vector<uint8_t> SV;
  for (iter(datasets) i = 0; i < datasets.size(); ++i) {
    SV.insert(SV.end(), datasets[i][0].begin(), datasets[i][0].end());
    SV.push_back('\n');
  }
  SV.push_back('\0');

  vector<index_type> SA(SV.size());
  saisxx(SV.begin(), SA.begin(), (index_type)SV.size());

  WaveletMatrix wt_text(8);
  {
    vector<uint8_t> TV = bwt(SV);
    wt_text.init(TV);
  }

  WaveletMatrix wt_freq(9);
  {
    vector<uint64_t> array(SV.size());
    uint64_t sum = 0;
    for (iter(datasets) i = 0; i < datasets.size(); ++i) {
      for (iter(datasets[i][0]) j = 0; j < datasets[i][0].size(); ++j) {
        array[sum] = i;
        ++sum;
      }
      array[sum] = datasets.size();
      ++sum;
    }
    array[sum] = datasets.size();
    ++sum;

    vector<uint64_t> rev(SV.size());
    for (iter(SV) i = 0; i < SV.size(); ++i) {
      rev[i] = array[SA[i]];
    }
    wt_freq.init(rev);
  }

  if (parser.exist("query")) {
    string q = parser.get<string>("query");
    search(q, parser.get<int>("number"), wt_text, wt_freq, datasets);
  }

  if (parser.exist("interact")) {
    while (true) {
      cout << "query> ";
      string q;
      if (cin >> q) {
        search(q, parser.get<int>("number"), wt_text, wt_freq, datasets);
      } else {
        break;
      }
    }
  }
}
<commit_msg>mainmain.cppの見かけのメモリ使用量を削減した<commit_after>#include <iostream>
#include <algorithm>
#include <fstream>
#include <vector>
#include <string>
#include <type_traits>
#include <iomanip>

#include "cmdline/cmdline.h"
#include "picojson/picojson.h"
#include "sais/sais.hxx"
#include "wavelet_matrix.h"

using namespace std;

typedef int64_t index_type;
#define iter(c) decltype((c).size())

vector<uint8_t> bwt(const vector<uint8_t> &S) {
  vector<uint8_t> T(S.size());
  vector<index_type> tmp(S.size());

  vector<uint8_t> &S2 = const_cast<vector<uint8_t> &>(S);

  saisxx_bwt(S2.begin(), T.begin(), tmp.begin(), (index_type)S.size());

  return T;
}

vector<uint8_t> ibwt(const vector<uint8_t> &T, const index_type pid) {
  vector<uint64_t> C(256, 0);
  for (const auto &c : T) {
    ++C[c];
  }

  uint64_t sum = 0;
  for (iter(C) i = 0; i < C.size(); ++i) {
    uint64_t cur = C[i];
    C[i] = sum;
    sum += cur;
  }

  vector<index_type> phi(T.size());
  for (iter(T) i = 0; i < T.size(); ++i) {
    phi[C[T[i]]] = i;
    ++C[T[i]];
  }

  vector<uint8_t> S(T.size());
  index_type j = pid;
  for (iter(T) i = 0; i < T.size(); ++i) {
    S[i] = T[phi[j]];
    j = phi[j];
  }

  return S;
}

string read_oneline(const string &ifname) {
  ifstream ifs(ifname);

  if (!ifs) {
    perror(ifname.c_str());
    exit(EXIT_FAILURE);
  }

  string s;
  getline(ifs, s);
  return s;
}

void show_string_in_hex(const string &s) {
  for (iter(s) i = 0; i < s.size(); ++i) {
    if (i > 0)
      cout << ' ';
    unsigned char c = s[i];
    cerr << "0x" << hex << (int)c;
  }
  cerr << endl;
}

bool is_utf8_start_char(unsigned char c) {
  // 2バイト目以降は先頭ビットが10である
  if ((c >> 6) == 2)
    return false;
  return true;
}

pair<index_type, index_type> fm_index(const WaveletMatrix &wat,
                                      const string &p) {
  index_type sp = 0;
  index_type ep = wat.length();
  for (iter(p) i = 0; i < p.size(); ++i) {
    unsigned char c = p[p.size() - 1 - i];
    sp = wat.rank_lt(c) + wat.rank(c, sp);
    ep = wat.rank_lt(c) + wat.rank(c, ep);
    if (sp >= ep)
      return make_pair(-1, -1);
  }
  return make_pair(sp, ep);
}

vector<vector<string>> read_datasets(const string &cfname) {
  ifstream ifs(cfname);

  if (!ifs) {
    perror(cfname.c_str());
    exit(EXIT_FAILURE);
  }

  picojson::value json;
  string err = picojson::parse(json, ifs);

  if (!err.empty()) {
    cerr << err << endl;
    exit(EXIT_FAILURE);
  }

  picojson::array &array = json.get<picojson::array>();
  vector<vector<string>> ret;
  for (const picojson::value &it : array) {
    picojson::object book = it.get<picojson::object>();
    string filename = book["filename"].get<string>();
    string title = book["title"].get<string>();
    string author = book["author"].get<string>();
    vector<string> vs = { read_oneline(filename), title, author };
    ret.emplace_back(vs);
  }
  return ret;
}

void search(const string &query, const int num,
            const WaveletMatrix &wt_text,
            const WaveletMatrix &wt_freq,
            const vector<vector<string>> &datasets) {
  auto spep = fm_index(wt_text, query);
  vector<pair<WaveletMatrix::Index, int>> res = wt_freq.topk<int>(spep.first, spep.second, num);
  for (const auto &r : res) {
    if (r.second == datasets.size())
      continue;
    cout << r.first << '\t' << datasets[r.second][1] << '\t' << datasets[r.second][2]
         << endl;
  }
}

int main(int argc, char *argv[]) {
  cmdline::parser parser;
  parser.add<string>("config", 'c', "config json file", /* need = */ true);
  parser.add<string>("query", 'q', "query string", /* need = */ false);
  parser.add<int>("number", 'n', "display first `number` lines",
                  /* need = */ false, /* default = */ 20);
  parser.add("interact", 'i', "launch interactive shell");
  parser.add("help", 'h', "show help");

  if (!parser.parse(argc, argv) || parser.exist("help")) {
    cerr << parser.error_full() << parser.usage() << endl;
    exit(EXIT_FAILURE);
  }

  if (parser.exist("query") == false && parser.exist("interact") == false) {
    cerr << "you should enable --query or --interact" << endl;
    exit(EXIT_FAILURE);
  }

  string cfname = parser.get<string>("config");
  vector<vector<string>> datasets = read_datasets(cfname);

  WaveletMatrix wt_text(8);
  WaveletMatrix wt_freq(9);
  {
    vector<uint8_t> SV;
    for (iter(datasets) i = 0; i < datasets.size(); ++i) {
      SV.insert(SV.end(), datasets[i][0].begin(), datasets[i][0].end());
      SV.push_back('\n');
    }
    SV.push_back('\0');

    vector<index_type> SA(SV.size());
    saisxx(SV.begin(), SA.begin(), (index_type)SV.size());

    {
      vector<uint8_t> TV = bwt(SV);
      wt_text.init(TV);
    }

    {
      vector<uint64_t> array(SV.size());
      uint64_t sum = 0;
      for (iter(datasets) i = 0; i < datasets.size(); ++i) {
        for (iter(datasets[i][0]) j = 0; j < datasets[i][0].size(); ++j) {
          array[sum] = i;
          ++sum;
        }
        array[sum] = datasets.size();
        ++sum;
      }
      array[sum] = datasets.size();
      ++sum;

      vector<uint64_t> rev(SV.size());
      for (iter(SV) i = 0; i < SV.size(); ++i) {
        rev[i] = array[SA[i]];
      }
      wt_freq.init(rev);
    }
  }

  if (parser.exist("query")) {
    string q = parser.get<string>("query");
    search(q, parser.get<int>("number"), wt_text, wt_freq, datasets);
  }

  if (parser.exist("interact")) {
    while (true) {
      cout << "query> ";
      string q;
      if (cin >> q) {
        search(q, parser.get<int>("number"), wt_text, wt_freq, datasets);
      } else {
        break;
      }
    }
  }
}
<|endoftext|>


<commit_before>#include "NeuralNetwork.hpp"

using namespace std;

NeuralNetwork::NeuralNetwork(const int nbi, const int nbh, const int nbo, const bool regression)
	: ni(nbi+1), nh(nbh+1), no(nbo), regression(regression), ai(ni, 1.0), ah(nh, 1.0), ao(no, 1.0)
{
	wi = NeuralNetwork::makeMatrix(ni, nh);
	wo = NeuralNetwork::makeMatrix(nh, no);

	uniform_real_distribution<float> dist(-1, 1);

	for (int i = 0; i < ni; i++) {
		for (int j = 0; j < nh; j++) {
			wi[i][j] = dist(rng);
		}
	}

	for (int j = 0; j < nh; j++) {
		for (int k = 0; k < no; k++) {
			wo[j][k] = dist(rng);
		}
	}

	ci = makeMatrix(ni, nh);
	co = makeMatrix(nh, no);
}

vector<vector<float>> NeuralNetwork::makeMatrix(const int width, const int height, const float fill) {
	vector<vector<float>> matrix;
	for (int i = 0; i < width; i++) {
		matrix.push_back(vector<float>(height, fill));
	}

	return matrix;
}

float NeuralNetwork::sigmoid(const float x) {
	return tanh(x);
}

float NeuralNetwork::dsigmoid(const float y) {
	return 1.0 - y*y;
}

vector<float> NeuralNetwork::update(const vector<float>& inputs) {
		if (inputs.size() != ni-1) {
			throw string("wrong number of inputs");
		}

		for (unsigned int i = 0; i < ni-1; i++) {
			ai[i] = inputs[i];
		}

		for (unsigned int j = 0; j < nh-1; j++) {
			float total = 0.0;
			for (int i = 0; i < ni; i++) {
				total += ai[i] * wi[i][j];
			}

			ah[j] = sigmoid(total);
		}

		for (unsigned int k = 0; k < no; k++) {
			float total = 0.0;
			for (unsigned int j = 0; j < nh; j++) {
				total += ah[j] * wo[j][k];
			}

			ao[k] = total;
			if (!regression) {
				ao[k] = sigmoid(total);
			}
		}

		return ao;
}

float NeuralNetwork::backPropagate(const vector<float>& targets, const float lr, const float mf) {
	if (targets.size() != no) {
		throw string("wrong number of target values");
	}

	vector<float> output_deltas(no, 1.0);
	for (unsigned int k = 0; k < no; k++) {
		output_deltas[k] = targets[k] - ao[k];
		if (!regression) {
			output_deltas[k] = dsigmoid(ao[k])*output_deltas[k];
		}
	}

	vector<float> hidden_deltas(nh, 0.0);
	for (unsigned int j = 0; j < nh; j++) {
		float error = 0.0;
		for (unsigned int k = 0; k < no; k++) {
			error += output_deltas[k]*wo[j][k];
		}

		hidden_deltas[j] = dsigmoid(ah[j])*error;
	}

	for (unsigned int j = 0; j < nh; j++) {
		for (unsigned int k = 0; k < no; k++) {
			float change = output_deltas[k]*ah[j];
			wo[j][k] = wo[j][k] + lr*change + mf*co[j][k];
			co[j][k] = change;
		}
	}

	for (unsigned int i = 0; i < ni; i++) {
		for (unsigned int j = 0; j < nh; j++) {
			float change = hidden_deltas[j]*ai[i];
			wi[i][j] = wi[i][j] + lr*change + mf*ci[i][j];
			ci[i][j] = change;
		}
	}

	float error = 0.0;
	for (unsigned int k = 0; k < targets.size(); k++) {
		error += 0.5*((targets[k]-ao[k])*(targets[k]-ao[k]));
	}

	return error;
}

vector<vector<float>> NeuralNetwork::test(const vector<vector<vector<float>>>& patterns, const bool verbose) {
	vector<vector<float>> tmp;
	for (const auto& p : patterns) {
		if (verbose) {
			cout << p[0][0] << " -> " << update(p[0])[0] << endl;
		}

		tmp.push_back(update(p[0]));
	}

	return tmp;
}

void NeuralNetwork::train(const vector<vector<vector<float>>>& patterns, const int iterations, const float lr, const float mf, const bool verbose) {
	for (int i = 0; i < iterations; i++) {
		float error = 0;

		for (const auto& p : patterns) {
			update(p[0]);
			float tmp = backPropagate(p[1], lr, mf);
			error += tmp;
		}

		if (i % 100 == 0) {
			cout << "error rate = " << error << endl;
		}
	}
}

<commit_msg>another whitespace fix<commit_after>#include "NeuralNetwork.hpp"

using namespace std;

NeuralNetwork::NeuralNetwork(const int nbi, const int nbh, const int nbo, const bool regression)
	: ni(nbi+1), nh(nbh+1), no(nbo), regression(regression), ai(ni, 1.0), ah(nh, 1.0), ao(no, 1.0)
{
	wi = NeuralNetwork::makeMatrix(ni, nh);
	wo = NeuralNetwork::makeMatrix(nh, no);

	uniform_real_distribution<float> dist(-1, 1);

	for (int i = 0; i < ni; i++) {
		for (int j = 0; j < nh; j++) {
			wi[i][j] = dist(rng);
		}
	}

	for (int j = 0; j < nh; j++) {
		for (int k = 0; k < no; k++) {
			wo[j][k] = dist(rng);
		}
	}

	ci = makeMatrix(ni, nh);
	co = makeMatrix(nh, no);
}

vector<vector<float>> NeuralNetwork::makeMatrix(const int width, const int height, const float fill) {
	vector<vector<float>> matrix;
	for (int i = 0; i < width; i++) {
		matrix.push_back(vector<float>(height, fill));
	}

	return matrix;
}

float NeuralNetwork::sigmoid(const float x) {
	return tanh(x);
}

float NeuralNetwork::dsigmoid(const float y) {
	return 1.0 - y*y;
}

vector<float> NeuralNetwork::update(const vector<float>& inputs) {
	if (inputs.size() != ni-1) {
		throw string("wrong number of inputs");
	}

	for (unsigned int i = 0; i < ni-1; i++) {
		ai[i] = inputs[i];
	}

	for (unsigned int j = 0; j < nh-1; j++) {
		float total = 0.0;
		for (int i = 0; i < ni; i++) {
			total += ai[i] * wi[i][j];
		}

		ah[j] = sigmoid(total);
	}

	for (unsigned int k = 0; k < no; k++) {
		float total = 0.0;
		for (unsigned int j = 0; j < nh; j++) {
			total += ah[j] * wo[j][k];
		}

		ao[k] = total;
		if (!regression) {
			ao[k] = sigmoid(total);
		}
	}

	return ao;
}

float NeuralNetwork::backPropagate(const vector<float>& targets, const float lr, const float mf) {
	if (targets.size() != no) {
		throw string("wrong number of target values");
	}

	vector<float> output_deltas(no, 1.0);
	for (unsigned int k = 0; k < no; k++) {
		output_deltas[k] = targets[k] - ao[k];
		if (!regression) {
			output_deltas[k] = dsigmoid(ao[k])*output_deltas[k];
		}
	}

	vector<float> hidden_deltas(nh, 0.0);
	for (unsigned int j = 0; j < nh; j++) {
		float error = 0.0;
		for (unsigned int k = 0; k < no; k++) {
			error += output_deltas[k]*wo[j][k];
		}

		hidden_deltas[j] = dsigmoid(ah[j])*error;
	}

	for (unsigned int j = 0; j < nh; j++) {
		for (unsigned int k = 0; k < no; k++) {
			float change = output_deltas[k]*ah[j];
			wo[j][k] = wo[j][k] + lr*change + mf*co[j][k];
			co[j][k] = change;
		}
	}

	for (unsigned int i = 0; i < ni; i++) {
		for (unsigned int j = 0; j < nh; j++) {
			float change = hidden_deltas[j]*ai[i];
			wi[i][j] = wi[i][j] + lr*change + mf*ci[i][j];
			ci[i][j] = change;
		}
	}

	float error = 0.0;
	for (unsigned int k = 0; k < targets.size(); k++) {
		error += 0.5*((targets[k]-ao[k])*(targets[k]-ao[k]));
	}

	return error;
}

vector<vector<float>> NeuralNetwork::test(const vector<vector<vector<float>>>& patterns, const bool verbose) {
	vector<vector<float>> tmp;
	for (const auto& p : patterns) {
		if (verbose) {
			cout << p[0][0] << " -> " << update(p[0])[0] << endl;
		}

		tmp.push_back(update(p[0]));
	}

	return tmp;
}

void NeuralNetwork::train(const vector<vector<vector<float>>>& patterns, const int iterations, const float lr, const float mf, const bool verbose) {
	for (int i = 0; i < iterations; i++) {
		float error = 0;

		for (const auto& p : patterns) {
			update(p[0]);
			float tmp = backPropagate(p[1], lr, mf);
			error += tmp;
		}

		if (i % 100 == 0) {
			cout << "error rate = " << error << endl;
		}
	}
}

<|endoftext|>