<commit_before>#include "stdafx.h"
#include "spline_renderer.h"

#include <glm/gtx/spline.hpp>
#include <glm/gtx/compatibility.hpp> //for lerp

#include "asdf_multiplat/utilities/utilities.h"
#include "asdf_multiplat/data/gl_state.h"

namespace asdf {
namespace hexmap
{
    using namespace data;

namespace ui
{
    namespace
    {
        constexpr size_t default_subdivs_per_spline_segment = 10;
    }

    /// vertex spec allocation / definition
    gl_vertex_spec_<vertex_attrib::position3_t, vertex_attrib::color_t> spline_vertex_t::vertex_spec;

    /// Helper Func Declarations
    line_node_t interpolated_node(spline_t const& spline, size_t spline_node_ind, float t);
    std::vector<line_node_t> line_from_interpolated_spline(spline_t const& spline, size_t subdivisions_per_segment);
    line_node_t interpolate_linear(line_node_t const& start, line_node_t const& end, float t);
    line_node_t interpolate_bezier(line_node_t const& start, control_node_t const& cn_start, control_node_t const& cn_end, line_node_t const& end, float t);

    /// Member Func Definitions
    void spline_renderer_t::init(std::shared_ptr<shader_t> _shader)
    {
        shader = std::move(_shader);
        spline_polygon.initialize(shader);
    }

    // void spline_renderer_t::batch(spline_t const& spline)
    // {
    //     spline_batch.push_back(&spline);
    // }

    // void spline_renderer_t::batch(std::vector<spline_t> const& splines)
    // {
    //     spline_batch.reserve(spline_batch.size() + splines.size());

    //     for(size_t i = 0; i < splines.size(); ++i)
    //     {
    //         spline_batch.push_back(&(splines[i]));
    //     }
    // }

    void spline_renderer_t::rebuild_all()
    {
        if(!spline_list || (spline_list && spline_list->empty()))
            return;

        reticulated_splines.clear();

        /// reticulate splines
        auto& constructed_lines = reticulated_splines;             // I am lazy and aliasing the variable name
        //std::vector<std::vector<line_node_t>> constructed_lines; // instead of find/replace
        constructed_lines.reserve(spline_list->size());

        for(auto const& spline : *spline_list)
        {
            if(spline.size() > 1) //ignore splines with less than two points (and thus no segments)
            {
                constructed_lines.push_back( line_from_interpolated_spline(spline, default_subdivs_per_spline_segment) );
            }

        }

        constructed_lines.shrink_to_fit();

        if(constructed_lines.empty())
        {
            return;
        }

        //pre-loop to get size info
        size_t num_verts = 0;
        for(auto const& polyline : constructed_lines)
        {
            //not doing thickness yet, so only one vertex per polyline node
            num_verts += polyline.size();
        }

        /// set up renderable vertices
        polygon_<spline_vertex_t> verts;
        verts.resize(num_verts);

        size_t vert_ind = 0;
        for(auto const& polyline : constructed_lines)
        {
            for(auto const& line_vert : polyline)
            {
                verts[vert_ind].position = glm::vec3(line_vert.position, 0.0f);
                verts[vert_ind].color    = line_vert.color;

                ++vert_ind;
            }
        }

        ASSERT(vert_ind == num_verts, "Unexpected unset vertices in polyline");

        spline_polygon.set_data(verts);
    }

    void spline_renderer_t::render()
    {
        ASSERT(shader, "cannot render splines without a shader");

        if(!spline_list)
        {
            return;
        }
        else if(spline_list->size() != spline_node_count_cache.size())
        {
            rebuild_all();
        }

        //update spline node count cache and rebuild splines if dirty
        //TODO: optimize to only rebuild dirty splines instead of all of them
        bool dirty = false;
        spline_node_count_cache.resize(spline_list->size(), 0); //init new elements as 0
        for(size_t i = 0; i < spline_list->size(); ++i)
        {
            dirty |= ((*spline_list)[i].size() != spline_node_count_cache[i]);
            spline_node_count_cache[i] = (*spline_list)[i].size();
        }

        if(dirty)
        {
            rebuild_all();
        }

        //if after rebuilding, there are no verts to render, don't even bother with anything below
        if(spline_polygon.num_verts == 0)
        {
            return;
        }

        GL_State->bind(shader);
        shader->update_wvp_uniform();

        spline_polygon.render(GL_LINE_LOOP); //will change this to GL_TRIANGLES later when I implement thickness
    }

    /// Helper Func Definitions
    line_node_t interpolated_node(spline_t const& spline, size_t spline_node_ind, float t)
    {
        ASSERT(spline.nodes.size() > spline_node_ind, "out of bounds");

        switch(spline.spline_type)
        {
            case spline_t::linear:
            {
                return interpolate_linear(spline.nodes[spline_node_ind], spline.nodes[spline_node_ind+1], t);
            }
            case spline_t::bezier:
            {
                auto cn_ind = spline_node_ind * 2;

                ASSERT(spline.control_nodes.size() > cn_ind, "out of bounds");

                auto const& p0 = spline.nodes[spline_node_ind];
                auto const& p1 = spline.control_nodes[cn_ind];
                auto const& p2 = spline.control_nodes[cn_ind + 1];
                auto const& p3 = spline.nodes[spline_node_ind+1];

                return interpolate_bezier(p0, p1, p2, p3, t);
            }
        };

        return spline.nodes[spline_node_ind];
    }

    std::vector<line_node_t> line_from_interpolated_spline(spline_t const& spline, size_t subdivisions_per_segment)
    {
        std::vector<line_node_t> constructed_line;

        if(spline.size() == 0 || spline.spline_type == spline_t::linear)
            return spline.nodes;

        //space for the original nodes plus subdivisions
        constructed_line.reserve(spline.size() + subdivisions_per_segment * spline.size() - 1);

        for(size_t spline_node_ind = 0; spline_node_ind < spline.size() - 1; ++spline_node_ind)
        {
            //start node
            constructed_line.push_back(spline.nodes[spline_node_ind]);

            for(size_t i = 0; i < subdivisions_per_segment; ++i)
            {
                auto t = static_cast<float>( (i+1) / (subdivisions_per_segment+2) ); //i+1 becuase the 0th node is the spline's start node, not this one
                                                                                //subdivisions_per_segment+2 because
                constructed_line.push_back(interpolated_node(spline, spline_node_ind, t));
            }

            //end node
            constructed_line.push_back(spline.nodes[spline_node_ind+1]);
        }

        //todo: simpilfy spline by removing nodes that are relatively coplanar

        return constructed_line;
    }

    line_node_t interpolate_linear(line_node_t const& start, line_node_t const& end, float t)
    {
        line_node_t node;
        node.position  = glm::lerp(start.position,  end.position,  t);
        node.thickness = glm::lerp(start.thickness, end.thickness, t);
        node.color     = glm::lerp(start.color,     end.color,     t);

        return node;
    }

    line_node_t interpolate_bezier(line_node_t const& start, control_node_t const& cn_start, control_node_t const& cn_end, line_node_t const& end, float t)
    {
        line_node_t node;
        node.position = bezier(start.position, cn_start, cn_end, end.position, t);

        //TODO: do something non-linear for interpolating non-position attributes?
        node.thickness = glm::lerp(start.thickness, end.thickness, t);
        node.color = glm::lerp(start.color, end.color, t);

        return node;
    }
}
}
}<commit_msg>spline_renderer now uses GL_LINE_STRIP instead of GL_LINE_LOOP<commit_after>#include "stdafx.h"
#include "spline_renderer.h"

#include <glm/gtx/spline.hpp>
#include <glm/gtx/compatibility.hpp> //for lerp

#include "asdf_multiplat/utilities/utilities.h"
#include "asdf_multiplat/data/gl_state.h"

namespace asdf {
namespace hexmap
{
    using namespace data;

namespace ui
{
    namespace
    {
        constexpr size_t default_subdivs_per_spline_segment = 10;
    }

    /// vertex spec allocation / definition
    gl_vertex_spec_<vertex_attrib::position3_t, vertex_attrib::color_t> spline_vertex_t::vertex_spec;

    /// Helper Func Declarations
    line_node_t interpolated_node(spline_t const& spline, size_t spline_node_ind, float t);
    std::vector<line_node_t> line_from_interpolated_spline(spline_t const& spline, size_t subdivisions_per_segment);
    line_node_t interpolate_linear(line_node_t const& start, line_node_t const& end, float t);
    line_node_t interpolate_bezier(line_node_t const& start, control_node_t const& cn_start, control_node_t const& cn_end, line_node_t const& end, float t);

    /// Member Func Definitions
    void spline_renderer_t::init(std::shared_ptr<shader_t> _shader)
    {
        shader = std::move(_shader);
        spline_polygon.initialize(shader);
    }

    // void spline_renderer_t::batch(spline_t const& spline)
    // {
    //     spline_batch.push_back(&spline);
    // }

    // void spline_renderer_t::batch(std::vector<spline_t> const& splines)
    // {
    //     spline_batch.reserve(spline_batch.size() + splines.size());

    //     for(size_t i = 0; i < splines.size(); ++i)
    //     {
    //         spline_batch.push_back(&(splines[i]));
    //     }
    // }

    void spline_renderer_t::rebuild_all()
    {
        if(!spline_list || (spline_list && spline_list->empty()))
            return;

        reticulated_splines.clear();

        /// reticulate splines
        auto& constructed_lines = reticulated_splines;             // I am lazy and aliasing the variable name
        //std::vector<std::vector<line_node_t>> constructed_lines; // instead of find/replace
        constructed_lines.reserve(spline_list->size());

        for(auto const& spline : *spline_list)
        {
            if(spline.size() > 1) //ignore splines with less than two points (and thus no segments)
            {
                constructed_lines.push_back( line_from_interpolated_spline(spline, default_subdivs_per_spline_segment) );
            }

        }

        constructed_lines.shrink_to_fit();

        if(constructed_lines.empty())
        {
            return;
        }

        //pre-loop to get size info
        size_t num_verts = 0;
        for(auto const& polyline : constructed_lines)
        {
            //not doing thickness yet, so only one vertex per polyline node
            num_verts += polyline.size();
        }

        /// set up renderable vertices
        polygon_<spline_vertex_t> verts;
        verts.resize(num_verts);

        size_t vert_ind = 0;
        for(auto const& polyline : constructed_lines)
        {
            for(auto const& line_vert : polyline)
            {
                verts[vert_ind].position = glm::vec3(line_vert.position, 0.0f);
                verts[vert_ind].color    = line_vert.color;

                ++vert_ind;
            }
        }

        ASSERT(vert_ind == num_verts, "Unexpected unset vertices in polyline");

        spline_polygon.set_data(verts);
    }

    void spline_renderer_t::render()
    {
        ASSERT(shader, "cannot render splines without a shader");

        if(!spline_list)
        {
            return;
        }
        else if(spline_list->size() != spline_node_count_cache.size())
        {
            rebuild_all();
        }

        //update spline node count cache and rebuild splines if dirty
        //TODO: optimize to only rebuild dirty splines instead of all of them
        bool dirty = false;
        spline_node_count_cache.resize(spline_list->size(), 0); //init new elements as 0
        for(size_t i = 0; i < spline_list->size(); ++i)
        {
            dirty |= ((*spline_list)[i].size() != spline_node_count_cache[i]);
            spline_node_count_cache[i] = (*spline_list)[i].size();
        }

        if(dirty)
        {
            rebuild_all();
        }

        //if after rebuilding, there are no verts to render, don't even bother with anything below
        if(spline_polygon.num_verts == 0)
        {
            return;
        }

        GL_State->bind(shader);
        shader->update_wvp_uniform();

        spline_polygon.render(GL_LINE_STRIP); //will change this to GL_TRIANGLES later when I implement thickness
    }

    /// Helper Func Definitions
    line_node_t interpolated_node(spline_t const& spline, size_t spline_node_ind, float t)
    {
        ASSERT(spline.nodes.size() > spline_node_ind, "out of bounds");

        switch(spline.spline_type)
        {
            case spline_t::linear:
            {
                return interpolate_linear(spline.nodes[spline_node_ind], spline.nodes[spline_node_ind+1], t);
            }
            case spline_t::bezier:
            {
                auto cn_ind = spline_node_ind * 2;

                ASSERT(spline.control_nodes.size() > cn_ind, "out of bounds");

                auto const& p0 = spline.nodes[spline_node_ind];
                auto const& p1 = spline.control_nodes[cn_ind];
                auto const& p2 = spline.control_nodes[cn_ind + 1];
                auto const& p3 = spline.nodes[spline_node_ind+1];

                return interpolate_bezier(p0, p1, p2, p3, t);
            }
        };

        return spline.nodes[spline_node_ind];
    }

    std::vector<line_node_t> line_from_interpolated_spline(spline_t const& spline, size_t subdivisions_per_segment)
    {
        std::vector<line_node_t> constructed_line;

        if(spline.size() == 0 || spline.spline_type == spline_t::linear)
            return spline.nodes;

        //space for the original nodes plus subdivisions
        constructed_line.reserve(spline.size() + subdivisions_per_segment * spline.size() - 1);

        for(size_t spline_node_ind = 0; spline_node_ind < spline.size() - 1; ++spline_node_ind)
        {
            //start node
            constructed_line.push_back(spline.nodes[spline_node_ind]);

            for(size_t i = 0; i < subdivisions_per_segment; ++i)
            {
                auto t = static_cast<float>( (i+1) / (subdivisions_per_segment+2) ); //i+1 becuase the 0th node is the spline's start node, not this one
                                                                                //subdivisions_per_segment+2 because
                constructed_line.push_back(interpolated_node(spline, spline_node_ind, t));
            }

            //end node
            constructed_line.push_back(spline.nodes[spline_node_ind+1]);
        }

        //todo: simpilfy spline by removing nodes that are relatively coplanar

        return constructed_line;
    }

    line_node_t interpolate_linear(line_node_t const& start, line_node_t const& end, float t)
    {
        line_node_t node;
        node.position  = glm::lerp(start.position,  end.position,  t);
        node.thickness = glm::lerp(start.thickness, end.thickness, t);
        node.color     = glm::lerp(start.color,     end.color,     t);

        return node;
    }

    line_node_t interpolate_bezier(line_node_t const& start, control_node_t const& cn_start, control_node_t const& cn_end, line_node_t const& end, float t)
    {
        line_node_t node;
        node.position = bezier(start.position, cn_start, cn_end, end.position, t);

        //TODO: do something non-linear for interpolating non-position attributes?
        node.thickness = glm::lerp(start.thickness, end.thickness, t);
        node.color = glm::lerp(start.color, end.color, t);

        return node;
    }
}
}
}<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QFileDialog>
#include <QMessageBox>

#include "settings.h"
#include "settingsdialog.h"

SettingsDialog::SettingsDialog()
{
    setupUi(this);

#ifndef BUILD_UPDATECHECKER
    // Remove the update controls
    delete updateCheckbox;
    delete updateIntervalLabel;
    delete updateIntervalSpinBox;
#endif

    // Load the current values into the controls
    reload();
}

void SettingsDialog::accept()
{
    // General tab
    Settings::set(Settings::DeviceName, deviceNameEdit->text());
    Settings::set(Settings::TransferDirectory, transferDirectoryEdit->text());

#ifdef BUILD_UPDATECHECKER
    Settings::set(Settings::UpdateInterval, updateCheckbox->isChecked() ? updateIntervalSpinBox->value() * Settings::Hour : 0);
#endif

    // Transfer section
    Settings::set(Settings::TransferPort, transferPortSpinBox->value());
    Settings::set(Settings::TransferBuffer, transferBufferSpinBox->value() * Settings::KiB);

    // Broadcast section
    Settings::set(Settings::BroadcastPort, broadcastPortSpinBox->value());
    Settings::set(Settings::BroadcastTimeout, broadcastTimeoutSpinBox->value() * Settings::Second);
    Settings::set(Settings::BroadcastInterval, broadcastIntervalSpinBox->value() * Settings::Second);

    QDialog::accept();
}

void SettingsDialog::onResetButtonClicked()
{
    // Confirm that the user wants to reset all of the settings
    QMessageBox::StandardButton response = QMessageBox::question(
        this,
        tr("Confirm Reset"),
        tr("Are you sure you want to reset all settings to their default values? This cannot be undone.")
    );

    // Perform the reset and then reload all of the settings
    if(response == QMessageBox::Yes) {
        Settings::reset();
        reload();
    }
}

void SettingsDialog::onTransferDirectoryButtonClicked()
{
    QString path = QFileDialog::getExistingDirectory(this, tr("Select Directory"), transferDirectoryEdit->text());
    if(!path.isNull()) {
        transferDirectoryEdit->setText(path);
    }
}

void SettingsDialog::reload()
{
    // General tab
    deviceNameEdit->setText(Settings::get(Settings::DeviceName).toString());
    transferDirectoryEdit->setText(Settings::get(Settings::TransferDirectory).toString());

#ifdef BUILD_UPDATECHECKER
    const int updateInterval = Settings::get(Settings::UpdateInterval).toInt();
    updateCheckbox->setChecked(updateInterval);
    updateIntervalSpinBox->setEnabled(updateInterval);
    updateIntervalSpinBox->setValue(updateInterval / Settings::Hour);
#endif

    // Transfer section
    transferPortSpinBox->setValue(Settings::get(Settings::TransferPort).toLongLong());
    transferBufferSpinBox->setValue(Settings::get(Settings::TransferBuffer).toInt() / Settings::KiB);

    // Broadcast section
    broadcastPortSpinBox->setValue(Settings::get(Settings::BroadcastPort).toLongLong());
    broadcastTimeoutSpinBox->setValue(Settings::get(Settings::BroadcastTimeout).toInt() / Settings::Second);
    broadcastIntervalSpinBox->setValue(Settings::get(Settings::BroadcastInterval).toInt() / Settings::Second);
}
<commit_msg>Modified SettingsDialog to use newly rewritten Settings class.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 **/

#include <QFileDialog>
#include <QMessageBox>

#include "settings.h"
#include "settingsdialog.h"

SettingsDialog::SettingsDialog()
{
    setupUi(this);

#ifndef BUILD_UPDATECHECKER
    // Remove the update controls
    delete updateCheckbox;
    delete updateIntervalLabel;
    delete updateIntervalSpinBox;
#endif

    // Load the current values into the controls
    reload();
}

void SettingsDialog::accept()
{
    Settings *settings = Settings::instance();
    settings->beginSet();

    // Settings in the general tab
    settings->set(Settings::Key::DeviceName, deviceNameEdit->text());
    settings->set(Settings::Key::TransferDirectory, transferDirectoryEdit->text());

#ifdef BUILD_UPDATECHECKER
    settings->set(Settings::Key::UpdateInterval, updateCheckbox->isChecked() ? updateIntervalSpinBox->value() * Settings::Constant::Hour : 0);
#endif

    // Settings in the transfer section
    settings->set(Settings::Key::TransferPort, transferPortSpinBox->value());
    settings->set(Settings::Key::TransferBuffer, transferBufferSpinBox->value() * Settings::Constant::KiB);

    // Settings in the broadcast section
    settings->set(Settings::Key::BroadcastPort, broadcastPortSpinBox->value());
    settings->set(Settings::Key::BroadcastTimeout, broadcastTimeoutSpinBox->value() * Settings::Constant::Second);
    settings->set(Settings::Key::BroadcastInterval, broadcastIntervalSpinBox->value() * Settings::Constant::Second);

    settings->endSet();
    QDialog::accept();
}

void SettingsDialog::onResetButtonClicked()
{
    // Confirm that the user wants to reset all of the settings
    QMessageBox::StandardButton response = QMessageBox::question(
        this,
        tr("Confirm Reset"),
        tr("Are you sure you want to reset all settings to their default values? This cannot be undone.")
    );

    // Perform the reset and then reload all of the settings
    if(response == QMessageBox::Yes) {
        Settings::instance()->reset();
        reload();
    }
}

void SettingsDialog::onTransferDirectoryButtonClicked()
{
    QString path = QFileDialog::getExistingDirectory(this, tr("Select Directory"), transferDirectoryEdit->text());
    if(!path.isNull()) {
        transferDirectoryEdit->setText(path);
    }
}

void SettingsDialog::reload()
{
    Settings *settings = Settings::instance();

    // General tab
    deviceNameEdit->setText(settings->get(Settings::Key::DeviceName).toString());
    transferDirectoryEdit->setText(settings->get(Settings::Key::TransferDirectory).toString());

#ifdef BUILD_UPDATECHECKER
    const int updateInterval = settings->get(Settings::Key::UpdateInterval).toInt();
    updateCheckbox->setChecked(updateInterval);
    updateIntervalSpinBox->setEnabled(updateInterval);
    updateIntervalSpinBox->setValue(updateInterval / Settings::Constant::Hour);
#endif

    // Transfer section
    transferPortSpinBox->setValue(settings->get(Settings::Key::TransferPort).toLongLong());
    transferBufferSpinBox->setValue(settings->get(Settings::Key::TransferBuffer).toInt() / Settings::Constant::KiB);

    // Broadcast section
    broadcastPortSpinBox->setValue(settings->get(Settings::Key::BroadcastPort).toLongLong());
    broadcastTimeoutSpinBox->setValue(settings->get(Settings::Key::BroadcastTimeout).toInt() / Settings::Constant::Second);
    broadcastIntervalSpinBox->setValue(settings->get(Settings::Key::BroadcastInterval).toInt() / Settings::Constant::Second);
}
<|endoftext|>


<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 "mitkDiffusionCoreObjectFactory.h"

#include "mitkProperties.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"

#include "mitkNrrdDiffusionImageIOFactory.h"
#include "mitkNrrdDiffusionImageWriterFactory.h"
#include "mitkNrrdDiffusionImageWriter.h"
#include "mitkDiffusionImage.h"

#include "mitkNrrdQBallImageIOFactory.h"
#include "mitkNrrdQBallImageWriterFactory.h"
#include "mitkNrrdQBallImageWriter.h"

#include "mitkNrrdTensorImageIOFactory.h"
#include "mitkNrrdTensorImageWriterFactory.h"
#include "mitkNrrdTensorImageWriter.h"

#include "mitkCompositeMapper.h"
#include "mitkDiffusionImageMapper.h"
#include "mitkGPUVolumeMapper3D.h"
#include "mitkVolumeDataVtkMapper3D.h"

#include "mitkPlanarFigureMapper3D.h"

typedef short DiffusionPixelType;

typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageShort;
typedef std::multimap<std::string, std::string> MultimapType;

mitk::DiffusionCoreObjectFactory::DiffusionCoreObjectFactory()
  :CoreObjectFactoryBase()
{

  static bool alreadyDone = false;
  if (!alreadyDone)
  {
    MITK_DEBUG << "DiffusionCoreObjectFactory c'tor" << std::endl;
    RegisterIOFactories();

    mitk::NrrdDiffusionImageIOFactory::RegisterOneFactory();
    mitk::NrrdQBallImageIOFactory::RegisterOneFactory();
    mitk::NrrdTensorImageIOFactory::RegisterOneFactory();

    mitk::NrrdDiffusionImageWriterFactory::RegisterOneFactory();
    mitk::NrrdQBallImageWriterFactory::RegisterOneFactory();
    mitk::NrrdTensorImageWriterFactory::RegisterOneFactory();

    m_FileWriters.push_back( NrrdDiffusionImageWriter<DiffusionPixelType>::New().GetPointer() );
    m_FileWriters.push_back( NrrdQBallImageWriter::New().GetPointer() );
    m_FileWriters.push_back( NrrdTensorImageWriter::New().GetPointer() );

    mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(this);
    CreateFileExtensionsMap();

    alreadyDone = true;
  }

}

mitk::Mapper::Pointer mitk::DiffusionCoreObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id)
{
  mitk::Mapper::Pointer newMapper=NULL;

  if ( id == mitk::BaseRenderer::Standard2D )
  {
    std::string classname("QBallImage");
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::CompositeMapper::New();
      newMapper->SetDataNode(node);
      node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper());
    }
    classname = "TensorImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::CompositeMapper::New();
      newMapper->SetDataNode(node);
      node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper());
    }

    classname = "DiffusionImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::DiffusionImageMapper<short>::New();
      newMapper->SetDataNode(node);
    }

  }
  else if ( id == mitk::BaseRenderer::Standard3D )
  {
    std::string classname("QBallImage");
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }
    classname = "TensorImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }
    classname = "DiffusionImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarRectangle";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarCircle";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarEllipse";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname = "PlanarPolygon";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

  }

  return newMapper;
}

void mitk::DiffusionCoreObjectFactory::SetDefaultProperties(mitk::DataNode* node)
{
  std::string classname = "QBallImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::CompositeMapper::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "TensorImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::CompositeMapper::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "DiffusionImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::DiffusionImageMapper<short>::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarRectangle";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarEllipse";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarCircle";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarPolygon";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

}

const char* mitk::DiffusionCoreObjectFactory::GetFileExtensions()
{
  std::string fileExtension;
  this->CreateFileExtensions(m_FileExtensionsMap, fileExtension);
  return fileExtension.c_str();
}

mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetFileExtensionsMap()
{
  return m_FileExtensionsMap;
}

const char* mitk::DiffusionCoreObjectFactory::GetSaveFileExtensions()
{
  std::string fileExtension;
  this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension);
  return fileExtension.c_str();
}

mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetSaveFileExtensionsMap()
{
  return m_SaveFileExtensionsMap;
}

void mitk::DiffusionCoreObjectFactory::CreateFileExtensionsMap()
{
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dwi", "Diffusion Weighted Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdwi", "Diffusion Weighted Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.fsl", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.fslgz", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.qbi", "Q-Ball Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hqbi", "Q-Ball Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dti", "Tensor Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdti", "Tensor Images"));
  //  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pf", "Planar Figure File"));

  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dwi", "Diffusion Weighted Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdwi", "Diffusion Weighted Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.fsl", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.fslgz", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.qbi", "Q-Ball Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hqbi", "Q-Ball Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dti", "Tensor Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdti", "Tensor Images"));
  // m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.pf", "Planar Figure File"));

}

void mitk::DiffusionCoreObjectFactory::RegisterIOFactories()
{
}

struct RegisterDiffusionCoreObjectFactory{
  RegisterDiffusionCoreObjectFactory()
    : m_Factory( mitk::DiffusionCoreObjectFactory::New() )
  {
    mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory );
  }

  ~RegisterDiffusionCoreObjectFactory()
  {
    mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory );
  }

  mitk::DiffusionCoreObjectFactory::Pointer m_Factory;
};

static RegisterDiffusionCoreObjectFactory registerDiffusionCoreObjectFactory;

<commit_msg>remove RegisterIOFactories call<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 "mitkDiffusionCoreObjectFactory.h"

#include "mitkProperties.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"

#include "mitkNrrdDiffusionImageIOFactory.h"
#include "mitkNrrdDiffusionImageWriterFactory.h"
#include "mitkNrrdDiffusionImageWriter.h"
#include "mitkDiffusionImage.h"

#include "mitkNrrdQBallImageIOFactory.h"
#include "mitkNrrdQBallImageWriterFactory.h"
#include "mitkNrrdQBallImageWriter.h"

#include "mitkNrrdTensorImageIOFactory.h"
#include "mitkNrrdTensorImageWriterFactory.h"
#include "mitkNrrdTensorImageWriter.h"

#include "mitkCompositeMapper.h"
#include "mitkDiffusionImageMapper.h"
#include "mitkGPUVolumeMapper3D.h"
#include "mitkVolumeDataVtkMapper3D.h"

#include "mitkPlanarFigureMapper3D.h"

typedef short DiffusionPixelType;

typedef mitk::DiffusionImage<DiffusionPixelType> DiffusionImageShort;
typedef std::multimap<std::string, std::string> MultimapType;

mitk::DiffusionCoreObjectFactory::DiffusionCoreObjectFactory()
  :CoreObjectFactoryBase()
{

  static bool alreadyDone = false;
  if (!alreadyDone)
  {
    MITK_DEBUG << "DiffusionCoreObjectFactory c'tor" << std::endl;

    mitk::NrrdDiffusionImageIOFactory::RegisterOneFactory();
    mitk::NrrdQBallImageIOFactory::RegisterOneFactory();
    mitk::NrrdTensorImageIOFactory::RegisterOneFactory();

    mitk::NrrdDiffusionImageWriterFactory::RegisterOneFactory();
    mitk::NrrdQBallImageWriterFactory::RegisterOneFactory();
    mitk::NrrdTensorImageWriterFactory::RegisterOneFactory();

    m_FileWriters.push_back( NrrdDiffusionImageWriter<DiffusionPixelType>::New().GetPointer() );
    m_FileWriters.push_back( NrrdQBallImageWriter::New().GetPointer() );
    m_FileWriters.push_back( NrrdTensorImageWriter::New().GetPointer() );

    mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(this);
    CreateFileExtensionsMap();

    alreadyDone = true;
  }

}

mitk::Mapper::Pointer mitk::DiffusionCoreObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id)
{
  mitk::Mapper::Pointer newMapper=NULL;

  if ( id == mitk::BaseRenderer::Standard2D )
  {
    std::string classname("QBallImage");
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::CompositeMapper::New();
      newMapper->SetDataNode(node);
      node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper());
    }
    classname = "TensorImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::CompositeMapper::New();
      newMapper->SetDataNode(node);
      node->SetMapper(3, ((CompositeMapper*)newMapper.GetPointer())->GetImageMapper());
    }

    classname = "DiffusionImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::DiffusionImageMapper<short>::New();
      newMapper->SetDataNode(node);
    }

  }
  else if ( id == mitk::BaseRenderer::Standard3D )
  {
    std::string classname("QBallImage");
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }
    classname = "TensorImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }
    classname = "DiffusionImage";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::GPUVolumeMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarRectangle";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarCircle";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname =  "PlanarEllipse";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

    classname = "PlanarPolygon";
    if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
    {
      newMapper = mitk::PlanarFigureMapper3D::New();
      newMapper->SetDataNode(node);
    }

  }

  return newMapper;
}

void mitk::DiffusionCoreObjectFactory::SetDefaultProperties(mitk::DataNode* node)
{
  std::string classname = "QBallImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::CompositeMapper::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "TensorImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::CompositeMapper::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "DiffusionImage";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::DiffusionImageMapper<short>::SetDefaultProperties(node);
    mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarRectangle";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarEllipse";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarCircle";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

  classname = "PlanarPolygon";
  if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
  {
    mitk::PlanarFigureMapper3D::SetDefaultProperties(node);
  }

}

const char* mitk::DiffusionCoreObjectFactory::GetFileExtensions()
{
  std::string fileExtension;
  this->CreateFileExtensions(m_FileExtensionsMap, fileExtension);
  return fileExtension.c_str();
}

mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetFileExtensionsMap()
{
  return m_FileExtensionsMap;
}

const char* mitk::DiffusionCoreObjectFactory::GetSaveFileExtensions()
{
  std::string fileExtension;
  this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension);
  return fileExtension.c_str();
}

mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetSaveFileExtensionsMap()
{
  return m_SaveFileExtensionsMap;
}

void mitk::DiffusionCoreObjectFactory::CreateFileExtensionsMap()
{
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dwi", "Diffusion Weighted Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdwi", "Diffusion Weighted Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.fsl", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.fslgz", "Diffusion Weighted Images for FSL"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.qbi", "Q-Ball Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hqbi", "Q-Ball Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.dti", "Tensor Images"));
  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdti", "Tensor Images"));
  //  m_FileExtensionsMap.insert(std::pair<std::string, std::string>("*.pf", "Planar Figure File"));

  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dwi", "Diffusion Weighted Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdwi", "Diffusion Weighted Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.nii", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.fsl", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.fslgz", "Diffusion Weighted Images for FSL"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.qbi", "Q-Ball Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hqbi", "Q-Ball Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.dti", "Tensor Images"));
  m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.hdti", "Tensor Images"));
  // m_SaveFileExtensionsMap.insert(std::pair<std::string, std::string>("*.pf", "Planar Figure File"));

}

void mitk::DiffusionCoreObjectFactory::RegisterIOFactories()
{
}

struct RegisterDiffusionCoreObjectFactory{
  RegisterDiffusionCoreObjectFactory()
    : m_Factory( mitk::DiffusionCoreObjectFactory::New() )
  {
    mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory );
  }

  ~RegisterDiffusionCoreObjectFactory()
  {
    mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory );
  }

  mitk::DiffusionCoreObjectFactory::Pointer m_Factory;
};

static RegisterDiffusionCoreObjectFactory registerDiffusionCoreObjectFactory;

<|endoftext|>


<commit_before>// This file is part of Honeydew
// Honeydew is licensed under the MIT LICENSE. See the LICENSE file for more info.

#pragma once

#include <honeydew/task_t.hpp>

namespace honeydew
{

/**
* Class that allows for easy building of task_t* structures.
*  Usage is expected to be via daisy-chaining of function calls
*  onto this object like Task(func1).then(func2).also(func3);
*/
class Task
{
public:

    /**
    * Constructs a new, empty Task wrapper object.
    */
    Task();

    /**
    * Constructs a new task object with a given priority.
    * @arg function to schedule and call on the associated worker thread.
    * @arg worker the associated thread on which to run this action. Worker=0 means any worker.
    * @arg priority the absolute priority (priority) of this call.
    */
    Task(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Deleted copy constructor.
    */
    Task(const Task& other) = delete;

    /**
    * Move constructor.
    */
    Task(Task&& other);

    /**
    * Initializes a previously uninitialized task. This function throws std::runtime_error
    *  if the task was previously initialized.
    */
    void init(std::function<void()> action=0, size_t worker=0, uint64_t priority=0);

    /**
    * Deleted copy assignment.
    */
    Task& operator=(const Task& other) = delete;

    // Move assignment.
    Task& operator=(Task&& other);

    /**
    * Cleans up the internals of this object if necessary.
    */
    ~Task();

    /**
    * Schedules a task with the given priority to be run after the previous task(s)
    *   on the given worker thread
    * @arg action the task to be performed.
    * @arg worker the associated worker for this task to run on. Worker=0 means any worker.
    * @arg priority the priority of the task (added to the previous task's priority).
    */
    Task& then(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task with the given priority to be run after the previous task(s)
    *   on the given worker thread
    * @arg action the task to be performed.
    * @arg worker the associated worker for this task to run on. Worker=0 means any worker.
    * @arg priority the priority of the task (absolute, not added to previous task's priority).
    */
    Task& then_absolute(std::function<void()> action, size_t worker=0,  uint64_t priority=0);

    /*
    * Adds another task_t heirarchy as a then relationship to the end of this Task structure.
    * @arg other the root of another task heirarchy.
    * @return a reference to this task for daisy chaining.
    */
    Task& then(task_t* other);
    template<typename TaskType> Task& then(TaskType&& other) { return then(other.close()); }

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the priority of the task. (added to the previous task's priority).
    */
    Task& also(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the absolute priority of the task. (not added to the previous task's priority).
    */
    Task& also_absolute(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Adds another task_t* structure as an also relationship to this task. The other heirarchy
    *  will take place at the same time as the last level of tasks in this hierarchy.
    * @arg other the root of the other task heirarchy.
    * @return a reference to this task for daisy chaining.
    */
    Task& also(task_t* other);
    template<typename TaskType> Task& also(TaskType&& other) { return also(other.close()); }

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will not wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the priority of the task. (added to the previous task's priority).
    */
    Task& fork(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will not wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the absolute priority of the task. (not added to the previous task's priority).
    */
    Task& fork_absolute(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Adds another task heirarchy as a forked task onto this heirarchy.
    * @arg other the other task heirarchy to fork from the current leaf of this heirarchy.
    * @return this task.
    */
    Task& fork(task_t* other);
    template<typename TaskType> Task& fork(TaskType& other) { return fork(other.close()); }

    /**
    * Returns the associated task_t* of this object and then !empties this object!
    *  This function is intended to be used by the Honeydew implementing classes ONLY!
    * @return the root of the built task_t* structure.
    */
    task_t* close();

private:
    task_t *root, *or_root, *leaf;
};

}
<commit_msg>Renamed 'deadline' to priority. Added then, also, and fork task_t* methods.<commit_after>// This file is part of Honeydew
// Honeydew is licensed under the MIT LICENSE. See the LICENSE file for more info.

#pragma once

#include <honeydew/task_t.hpp>

namespace honeydew
{

/**
* Class that allows for easy building of task_t* structures.
*  Usage is expected to be via daisy-chaining of function calls
*  onto this object like Task(func1).then(func2).also(func3);
*/
class Task
{
public:

    /**
    * Constructs a new, empty Task wrapper object.
    */
    Task();

    /**
    * Constructs a new task object with a given priority.
    * @arg function to schedule and call on the associated worker thread.
    * @arg worker the associated thread on which to run this action. Worker=0 means any worker.
    * @arg priority the absolute priority (priority) of this call.
    */
    Task(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Deleted copy constructor.
    */
    Task(const Task& other) = delete;

    /**
    * Move constructor.
    */
    Task(Task&& other);

    /**
    * Initializes a previously uninitialized task. This function throws std::runtime_error
    *  if the task was previously initialized.
    */
    void init(std::function<void()> action=0, size_t worker=0, uint64_t priority=0);

    /**
    * Deleted copy assignment.
    */
    Task& operator=(const Task& other) = delete;

    // Move assignment.
    Task& operator=(Task&& other);

    /**
    * Cleans up the internals of this object if necessary.
    */
    ~Task();

    /**
    * Schedules a task with the given priority to be run after the previous task(s)
    *   on the given worker thread
    * @arg action the task to be performed.
    * @arg worker the associated worker for this task to run on. Worker=0 means any worker.
    * @arg priority the priority of the task (added to the previous task's priority).
    */
    Task& then(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task with the given priority to be run after the previous task(s)
    *   on the given worker thread
    * @arg action the task to be performed.
    * @arg worker the associated worker for this task to run on. Worker=0 means any worker.
    * @arg priority the priority of the task (absolute, not added to previous task's priority).
    */
    Task& then_absolute(std::function<void()> action, size_t worker=0,  uint64_t priority=0);

    /*
    * Adds another task_t heirarchy as a then relationship to the end of this Task structure.
    * @arg other the root of another task heirarchy.
    * @return a reference to this task for daisy chaining.
    */
    Task& then(task_t* other);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the priority of the task. (added to the previous task's priority).
    */
    Task& also(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the absolute priority of the task. (not added to the previous task's priority).
    */
    Task& also_absolute(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Adds another task_t* structure as an also relationship to this task. The other heirarchy
    *  will take place at the same time as the last level of tasks in this hierarchy.
    * @arg other the root of the other task heirarchy.
    * @return a reference to this task for daisy chaining.
    */
    Task& also(task_t* other);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will not wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the priority of the task. (added to the previous task's priority).
    */
    Task& fork(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Schedules a task to occur concurrently with the previous task with the given priority
    *  on the associated worker thread. Further tasks will not wait for this task to complete.
    * @arg action the task to perform.
    * @arg worker the associated worker thread. Worker=0 means any worker.
    * @arg priority the absolute priority of the task. (not added to the previous task's priority).
    */
    Task& fork_absolute(std::function<void()> action, size_t worker=0, uint64_t priority=0);

    /**
    * Adds another task heirarchy as a forked task onto this heirarchy.
    * @arg other the other task heirarchy to fork from the current leaf of this heirarchy.
    * @return this task.
    */
    Task& fork(task_t* other);

    /**
    * Returns the associated task_t* of this object and then !empties this object!
    *  This function is intended to be used by the Honeydew implementing classes ONLY!
    * @return the root of the built task_t* structure.
    */
    task_t* close();

private:
    task_t *root, *or_root, *leaf;
};

}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2008 Gunnar Raetsch
 * Written (W) 1999-2008,2011 Soeren Sonnenburg
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 * Copyright (C) 2011 Berlin Institute of Technology
 */
#include <shogun/preprocessor/PCA.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/config.h>
#include <shogun/mathematics/Math.h>
#include <string.h>
#include <stdlib.h>
#include <shogun/lib/common.h>
#include <shogun/preprocessor/DensePreprocessor.h>
#include <shogun/features/Features.h>
#include <shogun/io/SGIO.h>

using namespace shogun;

CPCA::CPCA(bool do_whitening_, EPCAMode mode_, float64_t thresh_)
: CDimensionReductionPreprocessor(), num_dim(0), m_initialized(false),
	m_whitening(do_whitening_), m_mode(mode_), thresh(thresh_)
{
	init();
}

void CPCA::init()
{
	m_transformation_matrix = SGMatrix<float64_t>();
	m_mean_vector = SGVector<float64_t>();
	m_eigenvalues_vector = SGVector<float64_t>();

	SG_ADD(&m_transformation_matrix, "transformation_matrix",
	    "Transformation matrix (Eigenvectors of covariance matrix).",
	    MS_NOT_AVAILABLE);
	SG_ADD(&m_mean_vector, "mean_vector", "Mean Vector.", MS_NOT_AVAILABLE);
	SG_ADD(&m_eigenvalues_vector, "eigenvalues_vector",
	    "Vector with Eigenvalues.", MS_NOT_AVAILABLE);
	SG_ADD(&m_initialized, "initalized", "True when initialized.",
	    MS_NOT_AVAILABLE);
	SG_ADD(&m_whitening, "whitening", "Whether data shall be whitened.",
	    MS_AVAILABLE);
	SG_ADD((machine_int_t*) &m_mode, "mode", "PCA Mode.", MS_AVAILABLE);
	SG_ADD(&thresh, "thresh", "Cutoff threshold.", MS_AVAILABLE);
}

CPCA::~CPCA()
{
}

bool CPCA::init(CFeatures* features)
{
	if (!m_initialized)
	{
		// loop varibles
		int32_t i,j,k;

		ASSERT(features->get_feature_class()==C_DENSE)
		ASSERT(features->get_feature_type()==F_DREAL)

		int32_t num_vectors=((CDenseFeatures<float64_t>*)features)->get_num_vectors();
		int32_t num_features=((CDenseFeatures<float64_t>*)features)->get_num_features();
		SG_INFO("num_examples: %ld num_features: %ld \n", num_vectors, num_features)

		m_mean_vector.vlen = num_features;
		m_mean_vector.vector = SG_CALLOC(float64_t, num_features);

		// sum
		SGMatrix<float64_t> feature_matrix = ((CDenseFeatures<float64_t>*)features)->get_feature_matrix();
		for (i=0; i<num_vectors; i++)
		{
			for (j=0; j<num_features; j++)
				m_mean_vector.vector[j] += feature_matrix.matrix[i*num_features+j];
		}

		//divide
		for (i=0; i<num_features; i++)
			m_mean_vector.vector[i] /= num_vectors;

		float64_t* cov = SG_CALLOC(float64_t, num_features*num_features);

		float64_t* sub_mean = SG_MALLOC(float64_t, num_features);

		for (i=0; i<num_vectors; i++)
		{
		for (k=0; k<num_features; k++)
		sub_mean[k]=feature_matrix.matrix[i*num_features+k]-m_mean_vector.vector[k];

		cblas_dger(CblasColMajor,
			           num_features,num_features,
			           1.0,sub_mean,1,
			           sub_mean,1,
			           cov, num_features);
		}

		SG_FREE(sub_mean);

		for (i=0; i<num_features; i++)
		{
			for (j=0; j<num_features; j++)
				cov[i*num_features+j]/=(num_vectors-1);
		}

		SG_INFO("Computing Eigenvalues ... ")

		m_eigenvalues_vector.vector = SGMatrix<float64_t>::compute_eigenvectors(cov,num_features,num_features);
		m_eigenvalues_vector.vlen = num_features;
		num_dim=0;

		if (m_mode == FIXED_NUMBER)
		{
			ASSERT(m_target_dim <= num_features)
			num_dim = m_target_dim;
		}
		if (m_mode == VARIANCE_EXPLAINED)
		{
			float64_t eig_sum = 0;
			for (i=0; i<num_features; i++)
				eig_sum += m_eigenvalues_vector.vector[i];

			float64_t com_sum = 0;
			for (i=num_features-1; i>-1; i--)
			{
				num_dim++;
				com_sum += m_eigenvalues_vector.vector[i];
				if (com_sum/eig_sum>=thresh)
					break;
			}
		}
		if (m_mode == THRESHOLD)
		{
			for (i=num_features-1; i>-1; i--)
			{
				if (m_eigenvalues_vector.vector[i]>thresh)
					num_dim++;
				else
					break;
			}
		}

		SG_INFO("Done\nReducing from %i to %i features..", num_features, num_dim)

		m_transformation_matrix = SGMatrix<float64_t>(num_features,num_dim);
		num_old_dim = num_features;

		int32_t offs=0;
		for (i=num_features-num_dim; i<num_features; i++)
		{
			for (k=0; k<num_features; k++)
				if (m_whitening)
					m_transformation_matrix.matrix[offs+k*num_dim] =
						cov[num_features*i+k]/sqrt(m_eigenvalues_vector.vector[i]);
				else
					m_transformation_matrix.matrix[offs+k*num_dim] =
						cov[num_features*i+k];
			offs++;
		}

		SG_FREE(cov);
		m_initialized = true;
		return true;
	}

	return false;
}

void CPCA::cleanup()
{
	m_transformation_matrix=SGMatrix<float64_t>();
}

SGMatrix<float64_t> CPCA::apply_to_feature_matrix(CFeatures* features)
{
	ASSERT(m_initialized)
	SGMatrix<float64_t> m = ((CDenseFeatures<float64_t>*) features)->get_feature_matrix();
	int32_t num_vectors = m.num_cols;
	int32_t num_features = m.num_rows;
	SG_INFO("get Feature matrix: %ix%i\n", num_vectors, num_features)

	if (m.matrix)
	{
		SG_INFO("Preprocessing feature matrix\n")
		float64_t* res = SG_MALLOC(float64_t, num_dim);
		float64_t* sub_mean = SG_MALLOC(float64_t, num_features);

		for (int32_t vec=0; vec<num_vectors; vec++)
		{
			int32_t i;

			for (i=0; i<num_features; i++)
				sub_mean[i] = m.matrix[num_features*vec+i] - m_mean_vector.vector[i];

			cblas_dgemv(CblasColMajor,CblasNoTrans,
			            num_dim,num_features,
			            1.0,m_transformation_matrix.matrix,num_dim,
			            sub_mean,1,
			            0.0,res,1);

			float64_t* m_transformed = &m.matrix[num_dim*vec];

			for (i=0; i<num_dim; i++)
				m_transformed[i] = res[i];
		}
		SG_FREE(res);
		SG_FREE(sub_mean);

		((CDenseFeatures<float64_t>*) features)->set_num_features(num_dim);
		((CDenseFeatures<float64_t>*) features)->get_feature_matrix(num_features, num_vectors);
		SG_INFO("new Feature matrix: %ix%i\n", num_vectors, num_features)
	}

	return m;
}

SGVector<float64_t> CPCA::apply_to_feature_vector(SGVector<float64_t> vector)
{
	float64_t* result = SG_MALLOC(float64_t, num_dim);
	float64_t* sub_mean = SG_MALLOC(float64_t, vector.vlen);

	for (int32_t i=0; i<vector.vlen; i++)
		sub_mean[i]=vector.vector[i]-m_mean_vector.vector[i];

	cblas_dgemv(CblasColMajor,CblasNoTrans,
	            num_dim,vector.vlen,
	            1.0,m_transformation_matrix.matrix,m_transformation_matrix.num_cols,
	            sub_mean,1,
	            0.0,result,1);

	SG_FREE(sub_mean);
	return SGVector<float64_t>(result,num_dim);
}

SGMatrix<float64_t> CPCA::get_transformation_matrix()
{
	return m_transformation_matrix;
}

SGVector<float64_t> CPCA::get_eigenvalues()
{
	return m_eigenvalues_vector;
}

SGVector<float64_t> CPCA::get_mean()
{
	return m_mean_vector;
}

#endif /* HAVE_LAPACK */
<commit_msg>apply_to_feature_matrix method fixed in PCA<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2008 Gunnar Raetsch
 * Written (W) 1999-2008,2011 Soeren Sonnenburg
 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 * Copyright (C) 2011 Berlin Institute of Technology
 */
#include <shogun/preprocessor/PCA.h>
#ifdef HAVE_LAPACK
#include <shogun/mathematics/lapack.h>
#include <shogun/lib/config.h>
#include <shogun/mathematics/Math.h>
#include <string.h>
#include <stdlib.h>
#include <shogun/lib/common.h>
#include <shogun/preprocessor/DensePreprocessor.h>
#include <shogun/features/Features.h>
#include <shogun/io/SGIO.h>
#include <shogun/mathematics/eigen3.h>

using namespace shogun;
using namespace Eigen;

CPCA::CPCA(bool do_whitening_, EPCAMode mode_, float64_t thresh_)
: CDimensionReductionPreprocessor(), num_dim(0), m_initialized(false),
	m_whitening(do_whitening_), m_mode(mode_), thresh(thresh_)
{
	init();
}

void CPCA::init()
{
	m_transformation_matrix = SGMatrix<float64_t>();
	m_mean_vector = SGVector<float64_t>();
	m_eigenvalues_vector = SGVector<float64_t>();

	SG_ADD(&m_transformation_matrix, "transformation_matrix",
	    "Transformation matrix (Eigenvectors of covariance matrix).",
	    MS_NOT_AVAILABLE);
	SG_ADD(&m_mean_vector, "mean_vector", "Mean Vector.", MS_NOT_AVAILABLE);
	SG_ADD(&m_eigenvalues_vector, "eigenvalues_vector",
	    "Vector with Eigenvalues.", MS_NOT_AVAILABLE);
	SG_ADD(&m_initialized, "initalized", "True when initialized.",
	    MS_NOT_AVAILABLE);
	SG_ADD(&m_whitening, "whitening", "Whether data shall be whitened.",
	    MS_AVAILABLE);
	SG_ADD((machine_int_t*) &m_mode, "mode", "PCA Mode.", MS_AVAILABLE);
	SG_ADD(&thresh, "thresh", "Cutoff threshold.", MS_AVAILABLE);
}

CPCA::~CPCA()
{
}

bool CPCA::init(CFeatures* features)
{
	if (!m_initialized)
	{
		// loop varibles
		int32_t i,j,k;

		ASSERT(features->get_feature_class()==C_DENSE)
		ASSERT(features->get_feature_type()==F_DREAL)

		int32_t num_vectors=((CDenseFeatures<float64_t>*)features)->get_num_vectors();
		int32_t num_features=((CDenseFeatures<float64_t>*)features)->get_num_features();
		SG_INFO("num_examples: %ld num_features: %ld \n", num_vectors, num_features)

		m_mean_vector.vlen = num_features;
		m_mean_vector.vector = SG_CALLOC(float64_t, num_features);

		// sum
		SGMatrix<float64_t> feature_matrix = ((CDenseFeatures<float64_t>*)features)->get_feature_matrix();
		for (i=0; i<num_vectors; i++)
		{
			for (j=0; j<num_features; j++)
				m_mean_vector.vector[j] += feature_matrix.matrix[i*num_features+j];
		}

		//divide
		for (i=0; i<num_features; i++)
			m_mean_vector.vector[i] /= num_vectors;

		float64_t* cov = SG_CALLOC(float64_t, num_features*num_features);

		float64_t* sub_mean = SG_MALLOC(float64_t, num_features);

		for (i=0; i<num_vectors; i++)
		{
		for (k=0; k<num_features; k++)
		sub_mean[k]=feature_matrix.matrix[i*num_features+k]-m_mean_vector.vector[k];

		cblas_dger(CblasColMajor,
			           num_features,num_features,
			           1.0,sub_mean,1,
			           sub_mean,1,
			           cov, num_features);
		}

		SG_FREE(sub_mean);

		for (i=0; i<num_features; i++)
		{
			for (j=0; j<num_features; j++)
				cov[i*num_features+j]/=(num_vectors-1);
		}

		SG_INFO("Computing Eigenvalues ... ")

		m_eigenvalues_vector.vector = SGMatrix<float64_t>::compute_eigenvectors(cov,num_features,num_features);
		m_eigenvalues_vector.vlen = num_features;
		num_dim=0;

		if (m_mode == FIXED_NUMBER)
		{
			ASSERT(m_target_dim <= num_features)
			num_dim = m_target_dim;
		}
		if (m_mode == VARIANCE_EXPLAINED)
		{
			float64_t eig_sum = 0;
			for (i=0; i<num_features; i++)
				eig_sum += m_eigenvalues_vector.vector[i];

			float64_t com_sum = 0;
			for (i=num_features-1; i>-1; i--)
			{
				num_dim++;
				com_sum += m_eigenvalues_vector.vector[i];
				if (com_sum/eig_sum>=thresh)
					break;
			}
		}
		if (m_mode == THRESHOLD)
		{
			for (i=num_features-1; i>-1; i--)
			{
				if (m_eigenvalues_vector.vector[i]>thresh)
					num_dim++;
				else
					break;
			}
		}

		SG_INFO("Done\nReducing from %i to %i features..", num_features, num_dim)

		m_transformation_matrix = SGMatrix<float64_t>(num_features,num_dim);
		num_old_dim = num_features;

		int32_t offs=0;
		for (i=num_features-num_dim; i<num_features; i++)
		{
			for (k=0; k<num_features; k++)
				if (m_whitening)
					m_transformation_matrix.matrix[offs+k*num_dim] =
						cov[num_features*i+k]/sqrt(m_eigenvalues_vector.vector[i]);
				else
					m_transformation_matrix.matrix[offs+k*num_dim] =
						cov[num_features*i+k];
			offs++;
		}

		SG_FREE(cov);
		m_initialized = true;
		return true;
	}

	return false;
}

void CPCA::cleanup()
{
	m_transformation_matrix=SGMatrix<float64_t>();
}

#ifdef HAVE_EIGEN3
SGMatrix<float64_t> CPCA::apply_to_feature_matrix(CFeatures* features)
{
	ASSERT(m_initialized)
	SGMatrix<float64_t> m = ((CDenseFeatures<float64_t>*) features)->get_feature_matrix();
	int32_t num_vectors = m.num_cols;
	int32_t num_features = m.num_rows;
	SG_INFO("get Feature matrix: %ix%i\n", num_vectors, num_features)

	MatrixXd final_feature_matrix;

	if (m.matrix)
	{
		SG_INFO("Preprocessing feature matrix\n")
		Map<MatrixXd> feature_matrix(m.matrix, num_features, num_vectors);
		VectorXd data_mean = feature_matrix.rowwise().sum()/(float64_t) num_vectors;
		MatrixXd feature_matrix_centered = feature_matrix.colwise()-data_mean;

		SG_INFO("Transforming feature matrix\n")
		Map<MatrixXd> transform_matrix(m_transformation_matrix.matrix,
			m_transformation_matrix.num_rows, m_transformation_matrix.num_cols);
		final_feature_matrix = transform_matrix.transpose()*feature_matrix_centered;
	}

	SGMatrix<float64_t> result_matrix = SGMatrix<float64_t>(num_dim, num_vectors);
	for (int32_t c=0; c<num_vectors; c++)
	{
		for (int32_t r=0; r<num_dim; r++)
			result_matrix.matrix[c*num_dim+r] = final_feature_matrix(r,c);
	}

	return result_matrix;
}
#endif //HAVE_EIGEN3

SGVector<float64_t> CPCA::apply_to_feature_vector(SGVector<float64_t> vector)
{
	float64_t* result = SG_MALLOC(float64_t, num_dim);
	float64_t* sub_mean = SG_MALLOC(float64_t, vector.vlen);

	for (int32_t i=0; i<vector.vlen; i++)
		sub_mean[i]=vector.vector[i]-m_mean_vector.vector[i];

	cblas_dgemv(CblasColMajor,CblasNoTrans,
	            num_dim,vector.vlen,
	            1.0,m_transformation_matrix.matrix,m_transformation_matrix.num_cols,
	            sub_mean,1,
	            0.0,result,1);

	SG_FREE(sub_mean);
	return SGVector<float64_t>(result,num_dim);
}

SGMatrix<float64_t> CPCA::get_transformation_matrix()
{
	return m_transformation_matrix;
}

SGVector<float64_t> CPCA::get_eigenvalues()
{
	return m_eigenvalues_vector;
}

SGVector<float64_t> CPCA::get_mean()
{
	return m_mean_vector;
}

#endif /* HAVE_LAPACK */
<|endoftext|>


<commit_before>/**
 * @file: TeamSymbols.cpp
 * @author: Marcus Scheunemann
 *
 * First created on 9. April 2009, 18:10
 */

#include "TeamSymbols.h"

void TeamSymbols::registerSymbols(xabsl::Engine& engine)
{
  engine.registerDecimalInputSymbol("team.members_alive_count", &getTeamMembersAliveCount);
  engine.registerBooleanInputSymbol("team.calc_if_is_striker", &calculateIfStriker);
  engine.registerBooleanInputSymbol("team.calc_if_is_striker_by_time_to_ball", &calculateIfStriker_byTimeToBall);
  engine.registerBooleanOutputSymbol("team.is_playing_as_striker",&setWasStriker, &getWasStriker);
  engine.registerBooleanInputSymbol("team.calc_if_is_the_last", &calculateIfTheLast);
}

TeamSymbols* TeamSymbols::theInstance = NULL;

void TeamSymbols::execute()
{
}

double TeamSymbols::getTeamMembersAliveCount()
{
  int counter = 0;

  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=theInstance->getTeamMessage().data.begin();
    i != theInstance->getTeamMessage().data.end(); ++i)
  {
    const TeamMessage::Data& messageData = i->second;

    // "alive" means sent something in the last n seconds
    if(theInstance->getFrameInfo().getTimeSince(messageData.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime)
    {
      counter++;
    }
  }//end for

  return (double) counter;
}//end getTeamMembersAliveCount

bool TeamSymbols::getWasStriker()
{
  return theInstance->getPlayerInfo().isPlayingStriker;
}

void TeamSymbols::setWasStriker(bool striker)
{
  theInstance->getPlayerInfo().isPlayingStriker = striker;
}

bool TeamSymbols::calculateIfStriker()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  // initialize with max-values. Every Robot must start with same values!
  double shortestDistance = theInstance->getFieldInfo().xFieldLength;
  unsigned int playerNearestToBall = 0; //nobody near to ball

  //if someone is striker, leave! Goalie can be striker (while f.e. clearing ball)
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& messageData = i->second;
    const unsigned int number = i->first;

    if((theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime) && // the message is fresh...
        number != theInstance->getPlayerInfo().gameData.playerNumber && // its not me...
        messageData.wasStriker // the guy wants to be striker...
        ) {
      return false; // let him go :)
    }
  }//end for

  // all team members except goalie!! otherwise goalie is nearest and all thinks he is striker, but he won't clear ball
  //should check who has best position to goal etc.
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& messageData = i->second;
    const unsigned int number = i->first;

    double time_bonus = messageData.wasStriker?theInstance->parameters.strikerBonusTime:0.0;

    if (!messageData.fallen
      && !messageData.isPenalized
      && number != 1 // goalie is not considered
      && theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime // its fresh
      && (messageData.ballAge >= 0 && messageData.ballAge < theInstance->parameters.maxBallLostTime+time_bonus )// the guy sees the ball
      ) {
      Vector2d ballPos = messageData.ballPosition;
      double ballDistance = ballPos.abs();

      // striker bonus
      if (messageData.wasStriker)
        ballDistance -= 100;

      // remember the closest guy
      if(ballDistance < shortestDistance) {
        shortestDistance = ballDistance;
        playerNearestToBall = number;
      }
    }//end if
  }//end for

  // am I the closest one?
  return playerNearestToBall == theInstance->getPlayerInfo().gameData.playerNumber;
}//end calculateIfStriker

bool TeamSymbols::calculateIfStriker_byTimeToBall()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  double shortestTime = theInstance->getSoccerStrategy().timeToBall;
  if (theInstance->getPlayerInfo().isPlayingStriker)
    shortestTime-=100;

  for (std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& msg = i->second;
    unsigned int robotNumber = i->first;
    double failureProbability = 0.0;
    std::map<unsigned int, double>::const_iterator robotFailure = theInstance->getTeamMessageStatisticsModel().failureProbabilities.find(robotNumber);
    if (robotFailure != theInstance->getTeamMessageStatisticsModel().failureProbabilities.end()) {
      failureProbability = robotFailure->second;
    }
    if (robotNumber != theInstance->getPlayerInfo().gameData.playerNumber
      && msg.wasStriker //Robot considers itself the striker
      && !msg.isPenalized
      && failureProbability < theInstance->parameters.minFailureProbability //Message is fresh
      && msg.ballAge >= 0 //Ball has been seen
      && msg.ballAge + theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime) { //Ball is fresh
        if(msg.timeToBall < shortestTime) {
          return false;
        }
      }
  }//end for

  return true;

}//end calculateIfStriker_byTimeToBall

TeamSymbols::~TeamSymbols()
{
}

/** the robot which is closest to own goal is defined as the last one */
bool TeamSymbols::calculateIfTheLast()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  // initialize with own values
  double shortestDistance = (theInstance->getRobotPose().translation - theInstance->getFieldInfo().ownGoalCenter).abs();

  double secondShortestDistance = std::numeric_limits<double>::max();

  unsigned int playerNearestToOwnGoal = theInstance->getPlayerInfo().gameData.playerNumber;
  unsigned int playerAlmostNearestToOwnGoal = std::numeric_limits<unsigned int>::max();

  // check all non-penalized and non-striker team members
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin();
    i != tm.data.end(); ++i)
  {
    const TeamMessage::Data& messageData = i->second;
    const int number = i->first;

    if ((theInstance->getFrameInfo().getTimeSince(messageData.frameInfo.getTime())
         < theInstance->parameters.maximumFreshTime) && // alive?
        !messageData.isPenalized && // not penalized?
        !messageData.wasStriker &&
        number != 1 && // no goalie
        // we are already considered by the initial values
        messageData.playerNum != theInstance->getPlayerInfo().gameData.playerNumber
        )
    {
      Vector2d robotpos = messageData.pose.translation;
      double d = (robotpos-theInstance->getFieldInfo().ownGoalCenter).abs();
      if ( d < shortestDistance )
      {
       // std::cout << "(old) secDist=" << secondShortestDistance << " secNum="
       //           << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
       //           << " firstNum=" << playerNearestToOwnGoal << std::endl;

        // exchange the second shortest distance
        secondShortestDistance = shortestDistance;
        playerAlmostNearestToOwnGoal = playerNearestToOwnGoal;

        //std::cout << "(after exchange) secDist=" << secondShortestDistance << " secNum="
        //          << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
        //          << " firstNum=" << playerNearestToOwnGoal << std::endl;

        // set new nearest
        shortestDistance = d;
        playerNearestToOwnGoal = number;

        //std::cout << "(new) secDist=" << secondShortestDistance << " secNum="
        //          << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
        //          << " firstNum=" << playerNearestToOwnGoal << std::endl;
      }
    }//end if
  }//end for

//  std::cout << "==========" << std::endl;

  if(fabs(secondShortestDistance-shortestDistance) < 500)
  {
    // distance of distance is less than half a meter, choose if we have the
    // lowest player number
    if(playerNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber)
    {
      return playerNearestToOwnGoal < playerAlmostNearestToOwnGoal;
    }
    else if(playerAlmostNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber)
    {
      return playerAlmostNearestToOwnGoal < playerNearestToOwnGoal;
    }
    else
    {
      return false;
    }
  }
  else
  {
    // is it me?
    return playerNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber;
  }
}//end calculateIfTheLast
<commit_msg>Changed some comments.<commit_after>/**
 * @file: TeamSymbols.cpp
 * @author: Marcus Scheunemann
 *
 * First created on 9. April 2009, 18:10
 */

#include "TeamSymbols.h"

void TeamSymbols::registerSymbols(xabsl::Engine& engine)
{
  engine.registerDecimalInputSymbol("team.members_alive_count", &getTeamMembersAliveCount);
  engine.registerBooleanInputSymbol("team.calc_if_is_striker", &calculateIfStriker);
  engine.registerBooleanInputSymbol("team.calc_if_is_striker_by_time_to_ball", &calculateIfStriker_byTimeToBall);
  engine.registerBooleanOutputSymbol("team.is_playing_as_striker",&setWasStriker, &getWasStriker);
  engine.registerBooleanInputSymbol("team.calc_if_is_the_last", &calculateIfTheLast);
}

TeamSymbols* TeamSymbols::theInstance = NULL;

void TeamSymbols::execute()
{
}

double TeamSymbols::getTeamMembersAliveCount()
{
  int counter = 0;

  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=theInstance->getTeamMessage().data.begin();
    i != theInstance->getTeamMessage().data.end(); ++i)
  {
    const TeamMessage::Data& messageData = i->second;

    // "alive" means sent something in the last n seconds
    if(theInstance->getFrameInfo().getTimeSince(messageData.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime)
    {
      counter++;
    }
  }//end for

  return (double) counter;
}//end getTeamMembersAliveCount

bool TeamSymbols::getWasStriker()
{
  return theInstance->getPlayerInfo().isPlayingStriker;
}

void TeamSymbols::setWasStriker(bool striker)
{
  theInstance->getPlayerInfo().isPlayingStriker = striker;
}

bool TeamSymbols::calculateIfStriker()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  // initialize with max-values. Every Robot must start with same values!
  double shortestDistance = theInstance->getFieldInfo().xFieldLength;
  unsigned int playerNearestToBall = 0; //nobody near to ball

  //if someone is striker, leave! Goalie can be striker (while f.e. clearing ball)
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& messageData = i->second;
    const unsigned int number = i->first;

    if((theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime) && // the message is fresh...
        number != theInstance->getPlayerInfo().gameData.playerNumber && // its not me...
        messageData.wasStriker // the guy wants to be striker...
        ) {
      return false; // let him go :)
    }
  }//end for

  // all team members except goalie!! otherwise goalie is nearest and all thinks he is striker, but he won't clear ball
  //should check who has best position to goal etc.
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& messageData = i->second;
    const unsigned int number = i->first;

    double time_bonus = messageData.wasStriker?theInstance->parameters.strikerBonusTime:0.0;

    if (!messageData.fallen
      && !messageData.isPenalized
      && number != 1 // goalie is not considered
      && theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime // its fresh
      && (messageData.ballAge >= 0 && messageData.ballAge < theInstance->parameters.maxBallLostTime+time_bonus )// the guy sees the ball
      ) {
      Vector2d ballPos = messageData.ballPosition;
      double ballDistance = ballPos.abs();

      // striker bonus
      if (messageData.wasStriker)
        ballDistance -= 100;

      // remember the closest guy
      if(ballDistance < shortestDistance) {
        shortestDistance = ballDistance;
        playerNearestToBall = number;
      }
    }//end if
  }//end for

  // am I the closest one?
  return playerNearestToBall == theInstance->getPlayerInfo().gameData.playerNumber;
}//end calculateIfStriker

bool TeamSymbols::calculateIfStriker_byTimeToBall()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  double shortestTime = theInstance->getSoccerStrategy().timeToBall;
  if (theInstance->getPlayerInfo().isPlayingStriker)
    shortestTime-=100;

  for (std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin(); i != tm.data.end(); ++i) {
    const TeamMessage::Data& msg = i->second;
    unsigned int robotNumber = i->first;
    double failureProbability = 0.0;
    std::map<unsigned int, double>::const_iterator robotFailure = theInstance->getTeamMessageStatisticsModel().failureProbabilities.find(robotNumber);
    if (robotFailure != theInstance->getTeamMessageStatisticsModel().failureProbabilities.end()) {
      failureProbability = robotFailure->second;
    } //Failure probability will be 0, if there is no entry about this robot in the TeamMessageStatistics
    if (
      robotNumber != theInstance->getPlayerInfo().gameData.playerNumber //If this player is not us
      && msg.wasStriker //Robot considers itself the striker
      && !msg.isPenalized
      && failureProbability < theInstance->parameters.minFailureProbability //Message is fresh
      && msg.ballAge >= 0 //Ball has been seen
      && msg.ballAge + theInstance->getFrameInfo().getTimeSince(i->second.frameInfo.getTime()) < theInstance->parameters.maximumFreshTime //Ball is fresh
      && msg.timeToBall < shortestTime) { //Other player is closer to ball than us
      return false;
    }
  }//end for

  return true;

}//end calculateIfStriker_byTimeToBall

TeamSymbols::~TeamSymbols()
{
}

/** the robot which is closest to own goal is defined as the last one */
bool TeamSymbols::calculateIfTheLast()
{
  TeamMessage const& tm = theInstance->getTeamMessage();

  // initialize with own values
  double shortestDistance = (theInstance->getRobotPose().translation - theInstance->getFieldInfo().ownGoalCenter).abs();

  double secondShortestDistance = std::numeric_limits<double>::max();

  unsigned int playerNearestToOwnGoal = theInstance->getPlayerInfo().gameData.playerNumber;
  unsigned int playerAlmostNearestToOwnGoal = std::numeric_limits<unsigned int>::max();

  // check all non-penalized and non-striker team members
  for(std::map<unsigned int, TeamMessage::Data>::const_iterator i=tm.data.begin();
    i != tm.data.end(); ++i)
  {
    const TeamMessage::Data& messageData = i->second;
    const int number = i->first;

    if ((theInstance->getFrameInfo().getTimeSince(messageData.frameInfo.getTime())
         < theInstance->parameters.maximumFreshTime) && // alive?
        !messageData.isPenalized && // not penalized?
        !messageData.wasStriker &&
        number != 1 && // no goalie
        // we are already considered by the initial values
        messageData.playerNum != theInstance->getPlayerInfo().gameData.playerNumber
        )
    {
      Vector2d robotpos = messageData.pose.translation;
      double d = (robotpos-theInstance->getFieldInfo().ownGoalCenter).abs();
      if ( d < shortestDistance )
      {
       // std::cout << "(old) secDist=" << secondShortestDistance << " secNum="
       //           << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
       //           << " firstNum=" << playerNearestToOwnGoal << std::endl;

        // exchange the second shortest distance
        secondShortestDistance = shortestDistance;
        playerAlmostNearestToOwnGoal = playerNearestToOwnGoal;

        //std::cout << "(after exchange) secDist=" << secondShortestDistance << " secNum="
        //          << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
        //          << " firstNum=" << playerNearestToOwnGoal << std::endl;

        // set new nearest
        shortestDistance = d;
        playerNearestToOwnGoal = number;

        //std::cout << "(new) secDist=" << secondShortestDistance << " secNum="
        //          << playerAlmostNearestToOwnGoal << " firstDist=" << shortestDistance
        //          << " firstNum=" << playerNearestToOwnGoal << std::endl;
      }
    }//end if
  }//end for

//  std::cout << "==========" << std::endl;

  if(fabs(secondShortestDistance-shortestDistance) < 500)
  {
    // distance of distance is less than half a meter, choose if we have the
    // lowest player number
    if(playerNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber)
    {
      return playerNearestToOwnGoal < playerAlmostNearestToOwnGoal;
    }
    else if(playerAlmostNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber)
    {
      return playerAlmostNearestToOwnGoal < playerNearestToOwnGoal;
    }
    else
    {
      return false;
    }
  }
  else
  {
    // is it me?
    return playerNearestToOwnGoal == theInstance->getPlayerInfo().gameData.playerNumber;
  }
}//end calculateIfTheLast
<|endoftext|>