<commit_before>/*!
    \file console.cpp
    \brief Console management implementation
    \author Ivan Shynkarenka
    \date 29.07.2015
    \copyright MIT License
*/

#include "benchmark/console.h"

#include <cstdio>

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

namespace CppBenchmark {

std::ostream& operator<<(std::ostream& stream, Color color)
{
    Console::SetColor(color);
    return stream;
}

std::ostream& operator<<(std::ostream& stream, std::pair<Color, Color> colors)
{
    Console::SetColor(colors.first, colors.second);
    return stream;
}

void Console::SetColor(Color color, Color background)
{
#if defined(_WIN32) || defined(_WIN64)
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, (((WORD)color) & 0x0F) + ((((WORD)background) & 0x0F) << 4));
#elif defined(unix) || defined(__unix) || defined(__unix__)
    const char* colors[] =
    {
        "\033[22;30m",  // Black color
        "\033[22;34m",  // Blue color
        "\033[22;32m",  // Green color
        "\033[22;36m",  // Cyan color
        "\033[22;31m",  // Red color
        "\033[22;35m",  // Magenta color
        "\033[22;33m",  // Brown color
        "\033[22;37m",  // Grey color
        "\033[01;30m",  // Dark grey color
        "\033[01;34m",  // Light blue color
        "\033[01;32m",  // Light green color
        "\033[01;36m",  // Light cyan color
        "\033[01;31m",  // Light red color
        "\033[01;35m",  // Light magenta color
        "\033[01;33m",  // Yellow color
        "\033[01;37m"   // White color
    };
    const char* backgrounds[] =
    {
        "\033[22;40m",  // Black color
        "\033[22;44m",  // Blue color
        "\033[22;42m",  // Green color
        "\033[22;46m",  // Cyan color
        "\033[22;41m",  // Red color
        "\033[22;45m",  // Magenta color
        "\033[22;43m",  // Brown color
        "\033[22;47m",  // Grey color
        "\033[01;40m",  // Dark grey color
        "\033[01;44m",  // Light blue color
        "\033[01;42m",  // Light green color
        "\033[01;46m",  // Light cyan color
        "\033[01;41m",  // Light red color
        "\033[01;45m",  // Light magenta color
        "\033[01;43m",  // Yellow color
        "\033[01;47m"   // White color
    };
    std::fwrite(colors[(int)color - (int)Color::BLACK], 1, 8, stdout);
    std::fwrite(backgrounds[(int)background - (int)Color::BLACK], 1, 8, stdout);
#endif
}

} // namespace CppBenchmark
<commit_msg>Bugfixing<commit_after>/*!
    \file console.cpp
    \brief Console management implementation
    \author Ivan Shynkarenka
    \date 29.07.2015
    \copyright MIT License
*/

#include "benchmark/console.h"

#include <cstdio>

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

namespace CppBenchmark {

std::ostream& operator<<(std::ostream& stream, Color color)
{
    Console::SetColor(color);
    return stream;
}

std::ostream& operator<<(std::ostream& stream, std::pair<Color, Color> colors)
{
    Console::SetColor(colors.first, colors.second);
    return stream;
}

void Console::SetColor(Color color, Color background)
{
#if defined(_WIN32) || defined(_WIN64)
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, (((WORD)color) & 0x0F) + ((((WORD)background) & 0x0F) << 4));
#elif defined(unix) || defined(__unix) || defined(__unix__)
    const char* colors[] =
    {
        "\033[22;30m",  // Black color
        "\033[22;34m",  // Blue color
        "\033[22;32m",  // Green color
        "\033[22;36m",  // Cyan color
        "\033[22;31m",  // Red color
        "\033[22;35m",  // Magenta color
        "\033[22;33m",  // Brown color
        "\033[22;37m",  // Grey color
        "\033[01;30m",  // Dark grey color
        "\033[01;34m",  // Light blue color
        "\033[01;32m",  // Light green color
        "\033[01;36m",  // Light cyan color
        "\033[01;31m",  // Light red color
        "\033[01;35m",  // Light magenta color
        "\033[01;33m",  // Yellow color
        "\033[01;37m"   // White color
    };
    const char* backgrounds[] =
    {
        "\033[00000m",  // Black color
        "\033[02;44m",  // Blue color
        "\033[02;42m",  // Green color
        "\033[02;46m",  // Cyan color
        "\033[02;41m",  // Red color
        "\033[02;45m",  // Magenta color
        "\033[02;43m",  // Brown color
        "\033[02;47m",  // Grey color
        "\033[01;40m",  // Dark grey color
        "\033[01;44m",  // Light blue color
        "\033[01;42m",  // Light green color
        "\033[01;46m",  // Light cyan color
        "\033[01;41m",  // Light red color
        "\033[01;45m",  // Light magenta color
        "\033[01;43m",  // Yellow color
        "\033[01;47m"   // White color
    };
    std::fwrite(backgrounds[(int)background - (int)Color::BLACK], 1, 8, stdout);
    std::fwrite(colors[(int)color - (int)Color::BLACK], 1, 8, stdout);
#endif
}

} // namespace CppBenchmark
<|endoftext|>


<commit_before>#include "bioutils.h"
#include <sstream>
#include <ctype.h>

namespace com {
namespace goffersoft {
namespace apps {
namespace bio {

const char BioUtils::alphabets[] = { 'a', 't', 'c', 'g', 'n' };
const unsigned BioUtils::num_alphabets = sizeof(alphabets)/sizeof(char);

const char BioUtils::alphabets_compliment[] = { 't', 'a', 'g', 'c', 'n' };

using std::stringstream;

int BioUtils::is_alphabet(char alpha) {
  int i = 0;
  while(i < num_alphabets) {
    if(alphabets[i] == tolower(alpha))
      return i;
    i++;
  }
  return -1;
}

string&
BioUtils::_compliment(string& str1, const string& str, bool reverse) {
  int index;
  char tmp;

  for(int i = 0; i < str.length(); i++) {
    if((index = is_alphabet(str[i])) != -1) {
      tmp = alphabets_compliment[index];
    } else {
      tmp = str[i];
    }
    if(reverse)
      ((char *)(str1.c_str()))[str.length() - i - 1] = tmp;
    else
      ((char *)(str1.c_str()))[i] = tmp;
  }
  return str1;
}

string
BioUtils::compliment(const string& str) {
  string str1 = str;
  return _compliment(str1, str, false);
}

string
BioUtils::reverse_compliment(const string& str) {
  string str1 = str;
  return _compliment(str1, str, true);
}

//In information theory, the Hamming distance between
//two strings of equal length is the number of positions
//at which the corresponding symbols are different.
//In another way, it measures the minimum number of
//substitutions required to change one string into
//the other, or the minimum number of errors that could
//have transformed one string into the other.
unsigned
BioUtils::hamming_distance(const string& str1,
                           const string& str2,
                           unsigned length) {
  int len = min(str1.length(), str2.length());

  if(length > 0 && length < len) {
    len = length;
  }
  int hamming_distance = 0;

  for(int i = 0; i < len; i++)
  {
    if(tolower(str1[i]) != tolower(str2[i]))
      hamming_distance++;
  }

  return hamming_distance;
}

string
BioUtils::skew_graph(const string& str, unsigned length) {
  int numc = 0;
  int numg = 0;
  int i = 0;
  stringstream ss;

  int len = str.length();

  if(length > 0 && length < len) {
    len = length;
  }

  while (i < len) {
    if(tolower(str[i]) == 'c') {
      numc++;
    } else if (tolower(str[i]) == 'g') {
      numg++;
    }
    ss << numg - numc << ',';
    i++;
  }
  return ss.str();
}

} //com
} //goffersoft
} //apps
} //bio
<commit_msg>fix warnings<commit_after>#include "bioutils.h"
#include <sstream>
#include <ctype.h>

namespace com {
namespace goffersoft {
namespace apps {
namespace bio {

const char BioUtils::alphabets[] = { 'a', 't', 'c', 'g', 'n' };
const unsigned BioUtils::num_alphabets = sizeof(alphabets)/sizeof(char);

const char BioUtils::alphabets_compliment[] = { 't', 'a', 'g', 'c', 'n' };

using std::stringstream;

int BioUtils::is_alphabet(char alpha) {
  unsigned i = 0;
  while(i < num_alphabets) {
    if(alphabets[i] == tolower(alpha))
      return i;
    i++;
  }
  return -1;
}

string&
BioUtils::_compliment(string& str1, const string& str, bool reverse) {
  int index;
  char tmp;

  for(unsigned i = 0; i < str.length(); i++) {
    if((index = is_alphabet(str[i])) != -1) {
      tmp = alphabets_compliment[index];
    } else {
      tmp = str[i];
    }
    if(reverse)
      ((char *)(str1.c_str()))[str.length() - i - 1] = tmp;
    else
      ((char *)(str1.c_str()))[i] = tmp;
  }
  return str1;
}

string
BioUtils::compliment(const string& str) {
  string str1 = str;
  return _compliment(str1, str, false);
}

string
BioUtils::reverse_compliment(const string& str) {
  string str1 = str;
  return _compliment(str1, str, true);
}

//In information theory, the Hamming distance between
//two strings of equal length is the number of positions
//at which the corresponding symbols are different.
//In another way, it measures the minimum number of
//substitutions required to change one string into
//the other, or the minimum number of errors that could
//have transformed one string into the other.
unsigned
BioUtils::hamming_distance(const string& str1,
                           const string& str2,
                           unsigned length) {
  unsigned len = min(str1.length(), str2.length());

  if(length > 0 && length < len) {
    len = length;
  }
  int hamming_distance = 0;

  for(unsigned i = 0; i < len; i++)
  {
    if(tolower(str1[i]) != tolower(str2[i]))
      hamming_distance++;
  }

  return hamming_distance;
}

string
BioUtils::skew_graph(const string& str, unsigned length) {
  int numc = 0;
  int numg = 0;
  unsigned i = 0;
  stringstream ss;

  unsigned len = str.length();

  if(length > 0 && length < len) {
    len = length;
  }

  while (i < len) {
    if(tolower(str[i]) == 'c') {
      numc++;
    } else if (tolower(str[i]) == 'g') {
      numg++;
    }
    ss << numg - numc << ',';
    i++;
  }
  return ss.str();
}

} //com
} //goffersoft
} //apps
} //bio
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/
#ifndef DTK_DETAILS_TREE_TRAVERSAL_HPP
#define DTK_DETAILS_TREE_TRAVERSAL_HPP

#include <DTK_DBC.hpp>

#include <DTK_DetailsAlgorithms.hpp>
#include <DTK_DetailsNode.hpp>
#include <DTK_DetailsPriorityQueue.hpp>
#include <DTK_DetailsStack.hpp>
#include <DTK_Predicates.hpp>

namespace DataTransferKit
{

template <typename DeviceType>
class BoundingVolumeHierarchy;

namespace Details
{
template <typename DeviceType>
struct TreeTraversal
{
  public:
    using ExecutionSpace = typename DeviceType::execution_space;

    template <typename Predicate, typename... Args>
    KOKKOS_INLINE_FUNCTION static int
    query( BoundingVolumeHierarchy<DeviceType> const &bvh,
           Predicate const &pred, Args &&... args )
    {
        using Tag = typename Predicate::Tag;
        return queryDispatch( Tag{}, bvh, pred, std::forward<Args>( args )... );
    }

    /**
     * Return true if the node is a leaf.
     */
    KOKKOS_INLINE_FUNCTION
    static bool isLeaf( Node const *node )
    {
        return ( node->children.first == nullptr );
    }

    /**
     * Return the index of the leaf node.
     */
    KOKKOS_INLINE_FUNCTION
    static size_t getIndex( Node const *leaf )
    {
        static_assert( sizeof( size_t ) == sizeof( Node * ),
                       "Conversion is a bad idea if these sizes do not match" );
        return reinterpret_cast<size_t>( leaf->children.second );
    }

    /**
     * Return the root node of the BVH.
     */
    KOKKOS_INLINE_FUNCTION
    static Node const *getRoot( BoundingVolumeHierarchy<DeviceType> const &bvh )
    {
        if ( bvh.empty() )
            return nullptr;
        return ( bvh.size() > 1 ? bvh._internal_nodes : bvh._leaf_nodes )
            .data();
    }
};

// There are two (related) families of search: one using a spatial predicate and
// one using nearest neighbours query (see boost::geometry::queries
// documentation).
template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_FUNCTION int
spatialQuery( BoundingVolumeHierarchy<DeviceType> const &bvh,
              Predicate const &predicate, Insert const &insert )
{
    if ( bvh.empty() )
        return 0;

    if ( bvh.size() == 1 )
    {
        Node const *leaf = TreeTraversal<DeviceType>::getRoot( bvh );
        if ( predicate( leaf ) )
        {
            int const leaf_index = TreeTraversal<DeviceType>::getIndex( leaf );
            insert( leaf_index );
            return 1;
        }
        else
            return 0;
    }

    Stack<Node const *> stack;

    Node const *root = TreeTraversal<DeviceType>::getRoot( bvh );
    stack.push( root );
    int count = 0;

    while ( !stack.empty() )
    {
        Node const *node = stack.top();
        stack.pop();

        if ( TreeTraversal<DeviceType>::isLeaf( node ) )
        {
            insert( TreeTraversal<DeviceType>::getIndex( node ) );
            count++;
        }
        else
        {
            for ( Node const *child :
                  {node->children.first, node->children.second} )
            {
                if ( predicate( child ) )
                {
                    stack.push( child );
                }
            }
        }
    }
    return count;
}

// query k nearest neighbours
template <typename DeviceType, typename Distance, typename Insert>
KOKKOS_FUNCTION int
nearestQuery( BoundingVolumeHierarchy<DeviceType> const &bvh,
              Distance const &distance, int k, Insert const &insert )
{
    if ( bvh.empty() || k < 1 )
        return 0;

    if ( bvh.size() == 1 )
    {
        Node const *leaf = TreeTraversal<DeviceType>::getRoot( bvh );
        int const leaf_index = TreeTraversal<DeviceType>::getIndex( leaf );
        double const leaf_distance = distance( leaf );
        insert( leaf_index, leaf_distance );
        return 1;
    }

    using PairNodePtrDistance = Kokkos::pair<Node const *, double>;

    struct CompareDistance
    {
        KOKKOS_INLINE_FUNCTION bool
        operator()( PairNodePtrDistance const &lhs,
                    PairNodePtrDistance const &rhs ) const
        {
            // reverse order (larger distance means lower priority)
            return lhs.second > rhs.second;
        }
    };

    PriorityQueue<PairNodePtrDistance, CompareDistance> queue;
    // priority does not matter for the root since the node will be
    // processed directly and removed from the priority queue we don't even
    // bother computing the distance to it.
    Node const *root = TreeTraversal<DeviceType>::getRoot( bvh );
    queue.push( root, 0. );
    int count = 0;

    while ( !queue.empty() && count < k )
    {
        // get the node that is on top of the priority list (i.e. is the
        // closest to the query point)
        Node const *node = queue.top().first;
        double const node_distance = queue.top().second;
        // NOTE: it would be nice to be able to do something like
        // tie( node, node_distance = queue.top();

        // NOTE: not calling queue.pop() here so that it can be combined with
        // the next push in case the node is internal (thus sparing a bubble-up
        // operation)
        if ( TreeTraversal<DeviceType>::isLeaf( node ) )
        {
            queue.pop();
            insert( TreeTraversal<DeviceType>::getIndex( node ),
                    node_distance );
            count++;
        }
        else
        {
            // insert children of the node in the priority list

            auto const left_child = node->children.first;
            auto const right_child = node->children.second;
            queue.pop_push( left_child, distance( left_child ) );
            queue.push( right_child, distance( right_child ) );
        }
    }
    return count;
}

template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_INLINE_FUNCTION int
queryDispatch( SpatialPredicateTag,
               BoundingVolumeHierarchy<DeviceType> const &bvh,
               Predicate const &pred, Insert const &insert )
{
    return spatialQuery( bvh, pred, insert );
}

template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_INLINE_FUNCTION int queryDispatch(
    NearestPredicateTag, BoundingVolumeHierarchy<DeviceType> const &bvh,
    Predicate const &pred, Insert const &insert)
{
    auto const geometry = pred._geometry;
    auto const k = pred._k;
    return nearestQuery( bvh,
                         [geometry]( Node const *node ) {
                             return distance( geometry, node->bounding_box );
                         },
                         k, insert );
}

} // namespace Details
} // namespace DataTransferKit

#endif
<commit_msg>Pointless change in spatialQuery() witih emplace() to insert the root node into the stack instead of push()<commit_after>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/
#ifndef DTK_DETAILS_TREE_TRAVERSAL_HPP
#define DTK_DETAILS_TREE_TRAVERSAL_HPP

#include <DTK_DBC.hpp>

#include <DTK_DetailsAlgorithms.hpp>
#include <DTK_DetailsNode.hpp>
#include <DTK_DetailsPriorityQueue.hpp>
#include <DTK_DetailsStack.hpp>
#include <DTK_Predicates.hpp>

namespace DataTransferKit
{

template <typename DeviceType>
class BoundingVolumeHierarchy;

namespace Details
{
template <typename DeviceType>
struct TreeTraversal
{
  public:
    using ExecutionSpace = typename DeviceType::execution_space;

    template <typename Predicate, typename... Args>
    KOKKOS_INLINE_FUNCTION static int
    query( BoundingVolumeHierarchy<DeviceType> const &bvh,
           Predicate const &pred, Args &&... args )
    {
        using Tag = typename Predicate::Tag;
        return queryDispatch( Tag{}, bvh, pred, std::forward<Args>( args )... );
    }

    /**
     * Return true if the node is a leaf.
     */
    KOKKOS_INLINE_FUNCTION
    static bool isLeaf( Node const *node )
    {
        return ( node->children.first == nullptr );
    }

    /**
     * Return the index of the leaf node.
     */
    KOKKOS_INLINE_FUNCTION
    static size_t getIndex( Node const *leaf )
    {
        static_assert( sizeof( size_t ) == sizeof( Node * ),
                       "Conversion is a bad idea if these sizes do not match" );
        return reinterpret_cast<size_t>( leaf->children.second );
    }

    /**
     * Return the root node of the BVH.
     */
    KOKKOS_INLINE_FUNCTION
    static Node const *getRoot( BoundingVolumeHierarchy<DeviceType> const &bvh )
    {
        if ( bvh.empty() )
            return nullptr;
        return ( bvh.size() > 1 ? bvh._internal_nodes : bvh._leaf_nodes )
            .data();
    }
};

// There are two (related) families of search: one using a spatial predicate and
// one using nearest neighbours query (see boost::geometry::queries
// documentation).
template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_FUNCTION int
spatialQuery( BoundingVolumeHierarchy<DeviceType> const &bvh,
              Predicate const &predicate, Insert const &insert )
{
    if ( bvh.empty() )
        return 0;

    if ( bvh.size() == 1 )
    {
        Node const *leaf = TreeTraversal<DeviceType>::getRoot( bvh );
        if ( predicate( leaf ) )
        {
            int const leaf_index = TreeTraversal<DeviceType>::getIndex( leaf );
            insert( leaf_index );
            return 1;
        }
        else
            return 0;
    }

    Stack<Node const *> stack;

    stack.emplace( TreeTraversal<DeviceType>::getRoot( bvh ) );
    int count = 0;

    while ( !stack.empty() )
    {
        Node const *node = stack.top();
        stack.pop();

        if ( TreeTraversal<DeviceType>::isLeaf( node ) )
        {
            insert( TreeTraversal<DeviceType>::getIndex( node ) );
            count++;
        }
        else
        {
            for ( Node const *child :
                  {node->children.first, node->children.second} )
            {
                if ( predicate( child ) )
                {
                    stack.push( child );
                }
            }
        }
    }
    return count;
}

// query k nearest neighbours
template <typename DeviceType, typename Distance, typename Insert>
KOKKOS_FUNCTION int
nearestQuery( BoundingVolumeHierarchy<DeviceType> const &bvh,
              Distance const &distance, int k, Insert const &insert )
{
    if ( bvh.empty() || k < 1 )
        return 0;

    if ( bvh.size() == 1 )
    {
        Node const *leaf = TreeTraversal<DeviceType>::getRoot( bvh );
        int const leaf_index = TreeTraversal<DeviceType>::getIndex( leaf );
        double const leaf_distance = distance( leaf );
        insert( leaf_index, leaf_distance );
        return 1;
    }

    using PairNodePtrDistance = Kokkos::pair<Node const *, double>;

    struct CompareDistance
    {
        KOKKOS_INLINE_FUNCTION bool
        operator()( PairNodePtrDistance const &lhs,
                    PairNodePtrDistance const &rhs ) const
        {
            // reverse order (larger distance means lower priority)
            return lhs.second > rhs.second;
        }
    };

    PriorityQueue<PairNodePtrDistance, CompareDistance> queue;
    // priority does not matter for the root since the node will be
    // processed directly and removed from the priority queue we don't even
    // bother computing the distance to it.
    Node const *root = TreeTraversal<DeviceType>::getRoot( bvh );
    queue.push( root, 0. );
    int count = 0;

    while ( !queue.empty() && count < k )
    {
        // get the node that is on top of the priority list (i.e. is the
        // closest to the query point)
        Node const *node = queue.top().first;
        double const node_distance = queue.top().second;
        // NOTE: it would be nice to be able to do something like
        // tie( node, node_distance = queue.top();

        // NOTE: not calling queue.pop() here so that it can be combined with
        // the next push in case the node is internal (thus sparing a bubble-up
        // operation)
        if ( TreeTraversal<DeviceType>::isLeaf( node ) )
        {
            queue.pop();
            insert( TreeTraversal<DeviceType>::getIndex( node ),
                    node_distance );
            count++;
        }
        else
        {
            // insert children of the node in the priority list

            auto const left_child = node->children.first;
            auto const right_child = node->children.second;
            queue.pop_push( left_child, distance( left_child ) );
            queue.push( right_child, distance( right_child ) );
        }
    }
    return count;
}

template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_INLINE_FUNCTION int
queryDispatch( SpatialPredicateTag,
               BoundingVolumeHierarchy<DeviceType> const &bvh,
               Predicate const &pred, Insert const &insert )
{
    return spatialQuery( bvh, pred, insert );
}

template <typename DeviceType, typename Predicate, typename Insert>
KOKKOS_INLINE_FUNCTION int queryDispatch(
    NearestPredicateTag, BoundingVolumeHierarchy<DeviceType> const &bvh,
    Predicate const &pred, Insert const &insert)
{
    auto const geometry = pred._geometry;
    auto const k = pred._k;
    return nearestQuery( bvh,
                         [geometry]( Node const *node ) {
                             return distance( geometry, node->bounding_box );
                         },
                         k, insert );
}

} // namespace Details
} // namespace DataTransferKit

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Compiler.hpp"
#include "Platform.hpp"
#include "RegisterAllocation.hpp"
#include "SymbolTable.hpp"
#include "FunctionContext.hpp"

using namespace eddic;

void eddic::allocateParams(){
    PlatformDescriptor* descriptor = getPlatformDescriptor(platform);

    auto it = symbols.begin();
    auto end = symbols.end();

    while(it != end){
        auto function = it->second;

        if(function->context){
            for(auto parameter : function->parameters){
                auto type = parameter.paramType;
                unsigned int position = function->getParameterPositionByType(parameter.name);
                auto param = function->context->getVariable(parameter.name);

                if(type == BaseType::INT && position <= descriptor->numberOfIntParamRegisters()){
                    Position paramPosition(PositionType::PARAM_REGISTER, position);
                    param->setPosition(paramPosition);
                } else if(type == BaseType::FLOAT && position <= descriptor->numberOfFloatParamRegisters()){
                    Position paramPosition(PositionType::PARAM_REGISTER, position);
                    param->setPosition(paramPosition);
                }
            }
        }

        ++it;
    }
}
<commit_msg>Fix bug with the parameter allocator: the following have to change their position offsets<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "Compiler.hpp"
#include "Platform.hpp"
#include "RegisterAllocation.hpp"
#include "SymbolTable.hpp"
#include "FunctionContext.hpp"

using namespace eddic;

void eddic::allocateParams(){
    PlatformDescriptor* descriptor = getPlatformDescriptor(platform);

    auto it = symbols.begin();
    auto end = symbols.end();

    while(it != end){
        auto function = it->second;

        if(function->context){
            for(unsigned int i = 0; i < function->parameters.size(); ++i){
                auto& parameter = function->parameters[i];
                auto type = parameter.paramType;
                unsigned int position = function->getParameterPositionByType(parameter.name);
                auto param = function->context->getVariable(parameter.name);

                Position oldPosition = param->position();

                if(type == BaseType::INT && position <= descriptor->numberOfIntParamRegisters()){
                    Position paramPosition(PositionType::PARAM_REGISTER, position);
                    param->setPosition(paramPosition);
                } else if(type == BaseType::FLOAT && position <= descriptor->numberOfFloatParamRegisters()){
                    Position paramPosition(PositionType::PARAM_REGISTER, position);
                    param->setPosition(paramPosition);
                }

                //If the parameter has been changed
                if(param->position().isParamRegister()){
                    //We have to change the position of the all the following parameters
                    for(unsigned int j = i + 1; j < function->parameters.size(); ++j){
                        auto p = function->context->getVariable(function->parameters[j].name);
                        Position paramPosition = p->position();
                        p->setPosition(oldPosition);
                        oldPosition = paramPosition;
                    }
                }
            }
        }

        ++it;
    }
}
<|endoftext|>


<commit_before>#ifndef KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_
#define KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_

#include <ros/ros.h>
#include <std_msgs/Header.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/PoseWithCovariance.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <nav_msgs/Odometry.h>
#include <visualization_msgs/Marker.h>
#include "rviz_helper/colors.hpp"
#include "rviz_helper/tf_publisher.hpp"

namespace kr {
namespace viz {

using visualization_msgs::Marker;
using geometry_msgs::PoseWithCovariance;
using geometry_msgs::PoseWithCovarianceStamped;

/**
 * @brief The MarkerVisualizer class
 */
class MarkerVisualizer {
 public:
  /**
   * @brief MarkerVisualizer Ctor
   * @param nh ROS node handle
   * @param topic Topic name
   */
  MarkerVisualizer(const ros::NodeHandle &nh, const std::string &topic)
      : nh_(nh), pub_(nh_.advertise<Marker>(topic, 1)) {}

  /**
   * @brief setColor Set marker color
   */
  void SetColor(double r, double g, double b) {
    const rviz::Color color(r, g, b);
    SetColor(color);
  }

  /**
   * @brief setColor set marker color
   */
  void SetColor(const rviz::Color &color) {
    marker_.color.r = color.r_;
    marker_.color.g = color.g_;
    marker_.color.b = color.b_;
  }

  /**
   * @brief setAlpha Set marker alpha
   */
  void SetAlpha(double alpha) { marker_.color.a = alpha; }

  /**
   * @brief setScale
   */
  void SetScale(double s_x, double s_y = 1, double s_z = 1) {
    marker_.scale.x = s_x;
    marker_.scale.y = s_y;
    marker_.scale.z = s_z;
  }
  void SetScale(double *scale) { SetScale(scale[0], scale[1], scale[2]); }

  /**
   * @brief setLifetime Set marker lifetime
   */
  void SetLifetime(const ros::Duration &duration) {
    marker_.lifetime = duration;
  }

  /**
   * @brief SetAction Set marker action
   */
  void SetAction(unsigned int action) { marker_.action = action; }

  /**
   * @brief SetType Set marker type
   */
  void SetType(unsigned int type) { marker_.type = type; }

  void Publish(const Marker &marker) { pub_.publish(marker_); }

 protected:
  Marker marker_;  ///< Visualization marker

 private:
  ros::NodeHandle nh_;  ///< ROS node handle
  ros::Publisher pub_;  ///< ROS publisher
};

class TrajectoryVisualizer : public MarkerVisualizer {
 public:
  /**
   * @brief TrajectoryVisualizer Ctor
   * @param nh ROS node handle
   * @param topic Topic name
   */
  TrajectoryVisualizer(const ros::NodeHandle &nh,
                       const std::string &topic = "traj");

  /**
   * @brief set_num_skip
   * @param num_skip
   */
  void set_num_skip(int num_skip) { num_skip_ = num_skip; }

  /**
   * @brief PublishTrajectory Publish trajectory
   */
  void PublishTrajectory(const geometry_msgs::Point &point,
                         const std_msgs::Header &header);
  void PublishTrajectory(const geometry_msgs::Pose &pose,
                         const std_msgs::Header &header);

 private:
  int num_skip_{1};          ///< Number of points to skip, 1 keeps all
  int total_points_cnt_{0};  ///< Total points in marker
};

/**
 * @brief Visualize covariance as a scaled ellipsoid.
 */
class CovarianceVisualizer : public MarkerVisualizer {
 public:
  CovarianceVisualizer(const ros::NodeHandle &nh,
                       const std::string &topic = "covariance",
                       bool transforms_orientation = false);

  void PublishCovariance(const PoseWithCovariance &pose_cov,
                         const std_msgs::Header &header);
  void PublishCovariance(const PoseWithCovarianceStamped &pose_cov_stamped);
  void PublishCovariance(const nav_msgs::Odometry &odometry);
private:
  bool transform_orientation_{false};
};

/**
 * @brief The PoseVisualizer class
 * This visualizer will also publish a tf
 */
class PoseVisualizer : public TrajectoryVisualizer {
 public:
  PoseVisualizer(const ros::NodeHandle &nh, const std::string &topic = "traj",
                 const std::string &child_frame_id = "")
      : TrajectoryVisualizer(nh, topic), tf_pub_(child_frame_id) {}

  const std::string &child_frame_id() const { return tf_pub_.child_frame_id(); }
  void set_child_frame_id(const std::string &frame_id) {
    tf_pub_.set_child_frame_id(frame_id);
  }

  void PublishPose(const geometry_msgs::Pose &pose,
                   const std_msgs::Header &header);

 private:
  TfPublisher tf_pub_;
};

}  // namespace viz
}  // namespace kr

#endif  // KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_
<commit_msg>made markers default to alpha 1<commit_after>#ifndef KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_
#define KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_

#include <ros/ros.h>
#include <std_msgs/Header.h>
#include <geometry_msgs/Point.h>
#include <geometry_msgs/Pose.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/PoseWithCovariance.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <nav_msgs/Odometry.h>
#include <visualization_msgs/Marker.h>
#include "rviz_helper/colors.hpp"
#include "rviz_helper/tf_publisher.hpp"

namespace kr {
namespace viz {

using visualization_msgs::Marker;
using geometry_msgs::PoseWithCovariance;
using geometry_msgs::PoseWithCovarianceStamped;

/**
 * @brief The MarkerVisualizer class
 */
class MarkerVisualizer {
 public:
  /**
   * @brief MarkerVisualizer Ctor
   * @param nh ROS node handle
   * @param topic Topic name
   */
  MarkerVisualizer(const ros::NodeHandle &nh, const std::string &topic)
      : nh_(nh), pub_(nh_.advertise<Marker>(topic, 1)) {
    SetAlpha(1.0); // default alpha to visible
  }

  /**
   * @brief setColor Set marker color
   */
  void SetColor(double r, double g, double b) {
    const rviz::Color color(r, g, b);
    SetColor(color);
  }

  /**
   * @brief setColor set marker color
   */
  void SetColor(const rviz::Color &color) {
    marker_.color.r = color.r_;
    marker_.color.g = color.g_;
    marker_.color.b = color.b_;
  }

  /**
   * @brief setAlpha Set marker alpha
   */
  void SetAlpha(double alpha) { marker_.color.a = alpha; }

  /**
   * @brief setScale
   */
  void SetScale(double s_x, double s_y = 1, double s_z = 1) {
    marker_.scale.x = s_x;
    marker_.scale.y = s_y;
    marker_.scale.z = s_z;
  }
  void SetScale(double *scale) { SetScale(scale[0], scale[1], scale[2]); }

  /**
   * @brief setLifetime Set marker lifetime
   */
  void SetLifetime(const ros::Duration &duration) {
    marker_.lifetime = duration;
  }

  /**
   * @brief SetAction Set marker action
   */
  void SetAction(unsigned int action) { marker_.action = action; }

  /**
   * @brief SetType Set marker type
   */
  void SetType(unsigned int type) { marker_.type = type; }

  void Publish(const Marker &marker) { pub_.publish(marker_); }

 protected:
  Marker marker_;  ///< Visualization marker

 private:
  ros::NodeHandle nh_;  ///< ROS node handle
  ros::Publisher pub_;  ///< ROS publisher
};

class TrajectoryVisualizer : public MarkerVisualizer {
 public:
  /**
   * @brief TrajectoryVisualizer Ctor
   * @param nh ROS node handle
   * @param topic Topic name
   */
  TrajectoryVisualizer(const ros::NodeHandle &nh,
                       const std::string &topic = "traj");

  /**
   * @brief set_num_skip
   * @param num_skip
   */
  void set_num_skip(int num_skip) { num_skip_ = num_skip; }

  /**
   * @brief PublishTrajectory Publish trajectory
   */
  void PublishTrajectory(const geometry_msgs::Point &point,
                         const std_msgs::Header &header);
  void PublishTrajectory(const geometry_msgs::Pose &pose,
                         const std_msgs::Header &header);

 private:
  int num_skip_{1};          ///< Number of points to skip, 1 keeps all
  int total_points_cnt_{0};  ///< Total points in marker
};

/**
 * @brief Visualize covariance as a scaled ellipsoid.
 */
class CovarianceVisualizer : public MarkerVisualizer {
 public:
  CovarianceVisualizer(const ros::NodeHandle &nh,
                       const std::string &topic = "covariance",
                       bool transforms_orientation = false);

  void PublishCovariance(const PoseWithCovariance &pose_cov,
                         const std_msgs::Header &header);
  void PublishCovariance(const PoseWithCovarianceStamped &pose_cov_stamped);
  void PublishCovariance(const nav_msgs::Odometry &odometry);
private:
  bool transform_orientation_{false};
};

/**
 * @brief The PoseVisualizer class
 * This visualizer will also publish a tf
 */
class PoseVisualizer : public TrajectoryVisualizer {
 public:
  PoseVisualizer(const ros::NodeHandle &nh, const std::string &topic = "traj",
                 const std::string &child_frame_id = "")
      : TrajectoryVisualizer(nh, topic), tf_pub_(child_frame_id) {}

  const std::string &child_frame_id() const { return tf_pub_.child_frame_id(); }
  void set_child_frame_id(const std::string &frame_id) {
    tf_pub_.set_child_frame_id(frame_id);
  }

  void PublishPose(const geometry_msgs::Pose &pose,
                   const std_msgs::Header &header);

 private:
  TfPublisher tf_pub_;
};

}  // namespace viz
}  // namespace kr

#endif  // KR_VIZ_RVIZ_HELPER_MARKER_VISUALIZER_HPP_
<|endoftext|>


<commit_before>#pragma once

namespace my
{
    namespace impl
    {
        // http://rsdn.ru/Forum/?mid=1025325
        template <typename T, unsigned int N> char(&ArraySize(T(&)[N]))[N];
    }
}

// Number of elements in array. Compilation error if the type passed is not an array.
#define ARRAY_SIZE(X) sizeof(::my::impl::ArraySize(X))

// Make class noncopyable.
#define NONCOPYABLE(class_name)								\
private:													\
    class_name const & operator = (class_name const &);		\
    class_name(class_name const &);
/////////////////////////////////////////////////////////////

#define TO_STRING_IMPL(x) #x
#define TO_STRING(x) TO_STRING_IMPL(x)

#define UNUSED_VALUE(x) do { (void)(x); } while (false)

namespace my
{
  namespace impl
  {
    template <typename T> inline void ForceUseValue(T const & t)
    {
       volatile T dummy = t;
       UNUSED_VALUE(dummy);
    }
  }
}

// Prevent compiler optimization.
#define FORCE_USE_VALUE(x) ::my::impl::ForceUseValue(x)

#ifdef __GNUC__
#define PREDICT(x, prediction) __builtin_expect(x, prediction)
#define PREDICT_TRUE(x) __builtin_expect((x) != 0, 1)
#define PREDICT_FALSE(x) __builtin_expect((x) != 0, 0)
#else
#define PREDICT(x, prediction) (x)
#define PREDICT_TRUE(x) (x)
#define PREDICT_FALSE(x) (x)
#endif
<commit_msg>Better implementation for UNUSED_VALUE.<commit_after>#pragma once

namespace my
{
    namespace impl
    {
        // http://rsdn.ru/Forum/?mid=1025325
        template <typename T, unsigned int N> char(&ArraySize(T(&)[N]))[N];
    }
}

// Number of elements in array. Compilation error if the type passed is not an array.
#define ARRAY_SIZE(X) sizeof(::my::impl::ArraySize(X))

// Make class noncopyable.
#define NONCOPYABLE(class_name)								\
private:													\
    class_name const & operator = (class_name const &);		\
    class_name(class_name const &);
/////////////////////////////////////////////////////////////

#define TO_STRING_IMPL(x) #x
#define TO_STRING(x) TO_STRING_IMPL(x)

#define UNUSED_VALUE(x) static_cast<void>(x)

namespace my
{
  namespace impl
  {
    template <typename T> inline void ForceUseValue(T const & t)
    {
       volatile T dummy = t;
       UNUSED_VALUE(dummy);
    }
  }
}

// Prevent compiler optimization.
#define FORCE_USE_VALUE(x) ::my::impl::ForceUseValue(x)

#ifdef __GNUC__
#define PREDICT(x, prediction) __builtin_expect(x, prediction)
#define PREDICT_TRUE(x) __builtin_expect((x) != 0, 1)
#define PREDICT_FALSE(x) __builtin_expect((x) != 0, 0)
#else
#define PREDICT(x, prediction) (x)
#define PREDICT_TRUE(x) (x)
#define PREDICT_FALSE(x) (x)
#endif
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
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 "tensorflow/core/kernels/data/experimental/lmdb_dataset_op.h"

#include "tensorflow/core/kernels/data/dataset_test_base.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/platform/env.h"

namespace tensorflow {
namespace data {
namespace experimental {
namespace {

constexpr char kNodeName[] = "lmdb_dataset";
constexpr char kIteratorPrefix[] = "Iterator";
constexpr char kDataFileName[] = "data.mdb";
constexpr char kDataFileLoc[] = "tensorflow/core/lib/lmdb/testdata";

class LMDBDatasetParams : public DatasetParams {
 public:
  LMDBDatasetParams(std::vector<std::string> filenames,
                    DataTypeVector output_dtypes,
                    std::vector<PartialTensorShape> output_shapes,
                    string node_name)
      : DatasetParams(std::move(output_dtypes), std::move(output_shapes),
                      std::move(kNodeName)),
        filenames_(CreateTensor<std::string>(
            TensorShape({static_cast<int>(filenames.size())}), filenames)) {}

  virtual std::vector<Tensor> GetInputTensors() const override {
    return {filenames_};
  }

  virtual Status GetInputNames(
      std::vector<string>* input_names) const override {
    *input_names = {LMDBDatasetOp::kFileNames};
    return Status::OK();
  }

  virtual Status GetAttributes(AttributeVector* attributes) const override {
    *attributes = {{LMDBDatasetOp::kOutputTypes, output_dtypes_},
                   {LMDBDatasetOp::kOutputShapes, output_shapes_}};
    return Status::OK();
  }

  virtual string op_name() const override {
    return LMDBDatasetOp::kDatasetType;
  }

 private:
  // Names of binary database files to read, boxed up inside a Tensor of
  // strings
  Tensor filenames_;
};

class LMDBDatasetOpTest : public DatasetOpsTestBaseV2 {};

// Copy our test data file to the current test program's temporary
// directory, and return the full path to the copied file.
// This copying is necessary because LMDB creates lock files adjacent
// to files that it reads.
string MaybeCopyDataFile() {
  string src_loc = io::JoinPath(kDataFileLoc, kDataFileName);
  string dest_loc = io::JoinPath(testing::TmpDir(), kDataFileName);

  FileSystem* fs;  // Pointer to singleton
  TF_EXPECT_OK(Env::Default()->GetFileSystemForFile(src_loc, &fs));

  // FileSystem::FileExists currently returns Status::OK() if the file
  // exists and errors::NotFound() if the file doesn't exist. There's no
  // indication in the code or docs about whether other error codes may be
  // added in the future, so we code defensively here.
  Status exists_status = fs->FileExists(dest_loc);
  if (exists_status.code() == error::NOT_FOUND) {
    TF_EXPECT_OK(fs->CopyFile(src_loc, dest_loc));
  } else {
    TF_EXPECT_OK(exists_status);
  }

  return dest_loc;
}

LMDBDatasetParams SingleValidInput() {
  return {/*filenames=*/{MaybeCopyDataFile()},
          /*output_dtypes=*/{DT_STRING, DT_STRING},
          /*output_shapes=*/{PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams TwoValidInputs() {
  return {/*filenames*/ {MaybeCopyDataFile(), MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams EmptyInput() {
  return {/*filenames*/ {},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams InvalidPathAtStart() {
  return {/*filenames*/ {"This is not a valid filename", MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams InvalidPathInMiddle() {
  return {/*filenames*/ {MaybeCopyDataFile(), "This is not a valid filename",
                         MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

// The tensors we expect to see each time we read through the input data file.
const std::vector<Tensor> kFileOutput = CreateTensors<string>(
    TensorShape({}),
    {
        // Each call to GetNext() produces two scalar string tensors, but the
        // test harness expects to receive a flat vector
        {"0"}, {"a"},  //
        {"1"}, {"b"},  //
        {"2"}, {"c"},  //
        {"3"}, {"d"},  //
        {"4"}, {"e"},  //
        {"5"}, {"f"},  //
        {"6"}, {"g"},  //
        {"7"}, {"h"},  //
        {"8"}, {"i"},  //
        {"9"}, {"j"},  //
    });

std::vector<GetNextTestCase<LMDBDatasetParams>> GetNextTestCases() {
  // STL vectors don't have a "concatenate two vectors into a new vector"
  // operation, so...
  std::vector<Tensor> output_twice;
  output_twice.insert(output_twice.end(), kFileOutput.cbegin(),
                      kFileOutput.cend());
  output_twice.insert(output_twice.end(), kFileOutput.cbegin(),
                      kFileOutput.cend());

  return {
      {/*dataset_params=*/SingleValidInput(), /*expected_outputs=*/kFileOutput},
      {/*dataset_params=*/TwoValidInputs(), /*expected_outputs=*/output_twice},
      {/*dataset_params=*/EmptyInput(), /*expected_outputs=*/{}}};
}

ITERATOR_GET_NEXT_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                         GetNextTestCases());

TEST_F(LMDBDatasetOpTest, InvalidPathAtStart) {
  auto dataset_params = InvalidPathAtStart();
  TF_ASSERT_OK(Initialize(dataset_params));

  // Errors about invalid files are only raised when attempting to read data.
  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  std::vector<Tensor> next;

  Status get_next_status =
      iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence);

  EXPECT_EQ(get_next_status.code(), error::INVALID_ARGUMENT);
}

TEST_F(LMDBDatasetOpTest, InvalidPathInMiddle) {
  auto dataset_params = InvalidPathInMiddle();
  TF_ASSERT_OK(Initialize(dataset_params));

  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  std::vector<Tensor> next;

  // First 10 rows should be ok
  for (int i = 0; i < 10; ++i) {
    TF_ASSERT_OK(
        iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence));
    EXPECT_FALSE(end_of_sequence);
  }

  // Next read operation should raise an error
  Status get_next_status =
      iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence);
  EXPECT_EQ(get_next_status.code(), error::INVALID_ARGUMENT);
}

std::vector<DatasetNodeNameTestCase<LMDBDatasetParams>>
DatasetNodeNameTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_node_name=*/kNodeName}};
}

DATASET_NODE_NAME_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                         DatasetNodeNameTestCases());

std::vector<DatasetTypeStringTestCase<LMDBDatasetParams>>
DatasetTypeStringTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_dataset_type_string=*/name_utils::OpName(
               LMDBDatasetOp::kDatasetType)}};
}

DATASET_TYPE_STRING_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                           DatasetTypeStringTestCases());

std::vector<DatasetOutputDtypesTestCase<LMDBDatasetParams>>
DatasetOutputDtypesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_dtypes=*/{DT_STRING, DT_STRING}}};
}

DATASET_OUTPUT_DTYPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                             DatasetOutputDtypesTestCases());

std::vector<DatasetOutputShapesTestCase<LMDBDatasetParams>>
DatasetOutputShapesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_shapes=*/{PartialTensorShape({}),
                                       PartialTensorShape({})}}};
}

DATASET_OUTPUT_SHAPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                             DatasetOutputShapesTestCases());

std::vector<CardinalityTestCase<LMDBDatasetParams>> CardinalityTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_cardinality=*/kUnknownCardinality}};
}

DATASET_CARDINALITY_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                           CardinalityTestCases());

std::vector<IteratorOutputDtypesTestCase<LMDBDatasetParams>>
IteratorOutputDtypesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_dtypes=*/{DT_STRING, DT_STRING}}};
}

ITERATOR_OUTPUT_DTYPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                              IteratorOutputDtypesTestCases());

std::vector<IteratorOutputShapesTestCase<LMDBDatasetParams>>
IteratorOutputShapesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_shapes=*/{PartialTensorShape({}),
                                       PartialTensorShape({})}}};
}

ITERATOR_OUTPUT_SHAPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                              IteratorOutputShapesTestCases());

std::vector<IteratorPrefixTestCase<LMDBDatasetParams>>
IteratorOutputPrefixTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_iterator_prefix=*/name_utils::IteratorPrefix(
               LMDBDatasetOp::kDatasetType, kIteratorPrefix)}};
}

ITERATOR_PREFIX_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                       IteratorOutputPrefixTestCases());

// No test of save and restore; save/restore functionality is not implemented
// for this dataset.

}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<commit_msg>Update test case to latest version of test harness<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
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 "tensorflow/core/kernels/data/experimental/lmdb_dataset_op.h"

#include "tensorflow/core/kernels/data/dataset_test_base.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/platform/env.h"

namespace tensorflow {
namespace data {
namespace experimental {
namespace {

constexpr char kNodeName[] = "lmdb_dataset";
constexpr char kIteratorPrefix[] = "Iterator";
constexpr char kDataFileName[] = "data.mdb";
constexpr char kDataFileLoc[] = "tensorflow/core/lib/lmdb/testdata";

class LMDBDatasetParams : public DatasetParams {
 public:
  LMDBDatasetParams(std::vector<std::string> filenames,
                    DataTypeVector output_dtypes,
                    std::vector<PartialTensorShape> output_shapes,
                    string node_name)
      : DatasetParams(std::move(output_dtypes), std::move(output_shapes),
                      std::move(kNodeName)),
        filenames_(CreateTensor<std::string>(
            TensorShape({static_cast<int>(filenames.size())}), filenames)) {}

  virtual std::vector<Tensor> GetInputTensors() const override {
    return {filenames_};
  }

  virtual Status GetInputNames(
      std::vector<string>* input_names) const override {
    *input_names = {LMDBDatasetOp::kFileNames};
    return Status::OK();
  }

  virtual Status GetAttributes(AttributeVector* attributes) const override {
    *attributes = {{LMDBDatasetOp::kOutputTypes, output_dtypes_},
                   {LMDBDatasetOp::kOutputShapes, output_shapes_}};
    return Status::OK();
  }

  virtual string dataset_type() const override {
    return LMDBDatasetOp::kDatasetType;
  }

 private:
  // Names of binary database files to read, boxed up inside a Tensor of
  // strings
  Tensor filenames_;
};

class LMDBDatasetOpTest : public DatasetOpsTestBaseV2 {};

// Copy our test data file to the current test program's temporary
// directory, and return the full path to the copied file.
// This copying is necessary because LMDB creates lock files adjacent
// to files that it reads.
string MaybeCopyDataFile() {
  string src_loc = io::JoinPath(kDataFileLoc, kDataFileName);
  string dest_loc = io::JoinPath(testing::TmpDir(), kDataFileName);

  FileSystem* fs;  // Pointer to singleton
  TF_EXPECT_OK(Env::Default()->GetFileSystemForFile(src_loc, &fs));

  // FileSystem::FileExists currently returns Status::OK() if the file
  // exists and errors::NotFound() if the file doesn't exist. There's no
  // indication in the code or docs about whether other error codes may be
  // added in the future, so we code defensively here.
  Status exists_status = fs->FileExists(dest_loc);
  if (exists_status.code() == error::NOT_FOUND) {
    TF_EXPECT_OK(fs->CopyFile(src_loc, dest_loc));
  } else {
    TF_EXPECT_OK(exists_status);
  }

  return dest_loc;
}

LMDBDatasetParams SingleValidInput() {
  return {/*filenames=*/{MaybeCopyDataFile()},
          /*output_dtypes=*/{DT_STRING, DT_STRING},
          /*output_shapes=*/{PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams TwoValidInputs() {
  return {/*filenames*/ {MaybeCopyDataFile(), MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams EmptyInput() {
  return {/*filenames*/ {},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams InvalidPathAtStart() {
  return {/*filenames*/ {"This is not a valid filename", MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

LMDBDatasetParams InvalidPathInMiddle() {
  return {/*filenames*/ {MaybeCopyDataFile(), "This is not a valid filename",
                         MaybeCopyDataFile()},
          /*output_dtypes*/ {DT_STRING, DT_STRING},
          /*output_shapes*/ {PartialTensorShape({}), PartialTensorShape({})},
          /*node_name=*/kNodeName};
}

// The tensors we expect to see each time we read through the input data file.
const std::vector<Tensor> kFileOutput = CreateTensors<string>(
    TensorShape({}),
    {
        // Each call to GetNext() produces two scalar string tensors, but the
        // test harness expects to receive a flat vector
        {"0"}, {"a"},  //
        {"1"}, {"b"},  //
        {"2"}, {"c"},  //
        {"3"}, {"d"},  //
        {"4"}, {"e"},  //
        {"5"}, {"f"},  //
        {"6"}, {"g"},  //
        {"7"}, {"h"},  //
        {"8"}, {"i"},  //
        {"9"}, {"j"},  //
    });

std::vector<GetNextTestCase<LMDBDatasetParams>> GetNextTestCases() {
  // STL vectors don't have a "concatenate two vectors into a new vector"
  // operation, so...
  std::vector<Tensor> output_twice;
  output_twice.insert(output_twice.end(), kFileOutput.cbegin(),
                      kFileOutput.cend());
  output_twice.insert(output_twice.end(), kFileOutput.cbegin(),
                      kFileOutput.cend());

  return {
      {/*dataset_params=*/SingleValidInput(), /*expected_outputs=*/kFileOutput},
      {/*dataset_params=*/TwoValidInputs(), /*expected_outputs=*/output_twice},
      {/*dataset_params=*/EmptyInput(), /*expected_outputs=*/{}}};
}

ITERATOR_GET_NEXT_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                         GetNextTestCases());

TEST_F(LMDBDatasetOpTest, InvalidPathAtStart) {
  auto dataset_params = InvalidPathAtStart();
  TF_ASSERT_OK(Initialize(dataset_params));

  // Errors about invalid files are only raised when attempting to read data.
  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  std::vector<Tensor> next;

  Status get_next_status =
      iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence);

  EXPECT_EQ(get_next_status.code(), error::INVALID_ARGUMENT);
}

TEST_F(LMDBDatasetOpTest, InvalidPathInMiddle) {
  auto dataset_params = InvalidPathInMiddle();
  TF_ASSERT_OK(Initialize(dataset_params));

  bool end_of_sequence = false;
  std::vector<Tensor> out_tensors;
  std::vector<Tensor> next;

  // First 10 rows should be ok
  for (int i = 0; i < 10; ++i) {
    TF_ASSERT_OK(
        iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence));
    EXPECT_FALSE(end_of_sequence);
  }

  // Next read operation should raise an error
  Status get_next_status =
      iterator_->GetNext(iterator_ctx_.get(), &next, &end_of_sequence);
  EXPECT_EQ(get_next_status.code(), error::INVALID_ARGUMENT);
}

std::vector<DatasetNodeNameTestCase<LMDBDatasetParams>>
DatasetNodeNameTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_node_name=*/kNodeName}};
}

DATASET_NODE_NAME_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                         DatasetNodeNameTestCases());

std::vector<DatasetTypeStringTestCase<LMDBDatasetParams>>
DatasetTypeStringTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_dataset_type_string=*/name_utils::OpName(
               LMDBDatasetOp::kDatasetType)}};
}

DATASET_TYPE_STRING_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                           DatasetTypeStringTestCases());

std::vector<DatasetOutputDtypesTestCase<LMDBDatasetParams>>
DatasetOutputDtypesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_dtypes=*/{DT_STRING, DT_STRING}}};
}

DATASET_OUTPUT_DTYPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                             DatasetOutputDtypesTestCases());

std::vector<DatasetOutputShapesTestCase<LMDBDatasetParams>>
DatasetOutputShapesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_shapes=*/{PartialTensorShape({}),
                                       PartialTensorShape({})}}};
}

DATASET_OUTPUT_SHAPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                             DatasetOutputShapesTestCases());

std::vector<CardinalityTestCase<LMDBDatasetParams>> CardinalityTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_cardinality=*/kUnknownCardinality}};
}

DATASET_CARDINALITY_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                           CardinalityTestCases());

std::vector<IteratorOutputDtypesTestCase<LMDBDatasetParams>>
IteratorOutputDtypesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_dtypes=*/{DT_STRING, DT_STRING}}};
}

ITERATOR_OUTPUT_DTYPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                              IteratorOutputDtypesTestCases());

std::vector<IteratorOutputShapesTestCase<LMDBDatasetParams>>
IteratorOutputShapesTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_output_shapes=*/{PartialTensorShape({}),
                                       PartialTensorShape({})}}};
}

ITERATOR_OUTPUT_SHAPES_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                              IteratorOutputShapesTestCases());

std::vector<IteratorPrefixTestCase<LMDBDatasetParams>>
IteratorOutputPrefixTestCases() {
  return {{/*dataset_params=*/SingleValidInput(),
           /*expected_iterator_prefix=*/name_utils::IteratorPrefix(
               LMDBDatasetOp::kDatasetType, kIteratorPrefix)}};
}

ITERATOR_PREFIX_TEST_P(LMDBDatasetOpTest, LMDBDatasetParams,
                       IteratorOutputPrefixTestCases());

// No test of save and restore; save/restore functionality is not implemented
// for this dataset.

}  // namespace
}  // namespace experimental
}  // namespace data
}  // namespace tensorflow
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef __itkSliceBySliceImageFilter_hxx
#define __itkSliceBySliceImageFilter_hxx

#include "itkSliceBySliceImageFilter.h"
#include "itkProgressReporter.h"
#include "itkImageAlgorithm.h"

namespace itk
{
template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SliceBySliceImageFilter()
{
  m_InputFilter = ITK_NULLPTR;
  m_OutputFilter = ITK_NULLPTR;
  this->m_Dimension = ImageDimension - 1;
  m_SliceIndex = 0;
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::VerifyInputInformation()
{

  Superclass::VerifyInputInformation();

  // verify sane parameter
  if ( this->m_Dimension >= RegionType::ImageDimension )
    {
    itkExceptionMacro("Dimension selected for slicing is greater than ImageDimension");
    }

  if ( !m_InputFilter )
    {
    itkExceptionMacro("InputFilter must be set.");
    }

  if ( !m_OutputFilter )
    {
    itkExceptionMacro("OutputFilter must be set.");
    }

}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::GenerateInputRequestedRegion()
{
  // call the superclass's implementation of this method, which
  // propagates the output requested region to all inputs
  Superclass::GenerateInputRequestedRegion();

  InputDataObjectIterator it( this );
  InputImageType * input  = dynamic_cast< InputImageType * >( it.GetInput() );

  const RegionType &requestedInputRegion = input->GetRequestedRegion();

  // The requested region is the largest in all but the slice
  // dimension. In that dimension we can stream the requested
  // slices.
  RegionType inputRegion = input->GetLargestPossibleRegion();
  inputRegion.SetIndex( m_Dimension, requestedInputRegion.GetIndex(m_Dimension) );
  inputRegion.SetSize( m_Dimension, requestedInputRegion.GetSize(m_Dimension) );

  // Use the same requested region for each input, if an input image
  // is a different size and can't fulfill the request,
  // DataObject::PropagateRequestedRegion with throw
  while( !it.IsAtEnd() )
    {
    // get pointers to the input and output
    input  = dynamic_cast< InputImageType * >( it.GetInput() );

    if (input)
      {
      input->SetRequestedRegion( inputRegion );
      }
    ++it;
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetFilter(InputFilterType *filter)
{
  OutputFilterType *outputFilter = dynamic_cast< OutputFilterType * >( filter );

  if ( outputFilter == ITK_NULLPTR && filter != ITK_NULLPTR )
    {
    // TODO: can it be replaced by a concept check ?
    itkExceptionMacro(
      "Wrong output filter type. Use SetOutputFilter() and SetInputFilter() instead of SetFilter() when input and output filter types are different.");
    }
  this->SetInputFilter(filter);
  this->SetOutputFilter(outputFilter);
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetInputFilter(InputFilterType *filter)
{
  if ( !filter )
    {
    itkExceptionMacro("InputFilter cannot be NULL.");
    }

  if ( m_InputFilter.GetPointer() != filter )
    {
    this->Modified();
    m_InputFilter = filter;
    // adapt the number of inputs and outputs
    this->SetNumberOfRequiredInputs( filter->GetNumberOfValidRequiredInputs() );
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetOutputFilter(OutputFilterType *filter)
{
  if ( !filter )
    {
    itkExceptionMacro("OutputFilter cannot be NULL.");
    }

  if ( m_OutputFilter.GetPointer() != filter )
    {
    this->Modified();
    m_OutputFilter = filter;
    // adapt the number of inputs and outputs
    this->SetNumberOfRequiredOutputs( filter->GetNumberOfIndexedOutputs() );
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::GenerateData()
{

  const ProcessObject::DataObjectPointerArraySizeType numberOfIndexedInputs = this->GetNumberOfIndexedInputs();
  const ProcessObject::DataObjectPointerArraySizeType numberOfIndexedOutputs = this->GetNumberOfIndexedOutputs();

  this->AllocateOutputs();

  const RegionType requestedRegion = this->GetOutput( 0 )->GetRequestedRegion();
  const IndexType requestedIndex = requestedRegion.GetIndex();
  const SizeType requestedSize = requestedRegion.GetSize();

  InternalRegionType internalOutputRegion;
  InternalRegionType internalInputRegion;

  // copy the requested region to the internal slice region in
  // dimension order
  unsigned int internal_i = 0;
  for ( unsigned int i = 0; internal_i < InternalImageDimension; ++i, ++internal_i )
    {
    if ( i == this->m_Dimension )
      {
      ++i;
      }
    internalOutputRegion.SetSize( internal_i, requestedSize[i] );
    internalOutputRegion.SetIndex( internal_i, requestedIndex[i] );

    internalInputRegion.SetSize( internal_i, this->GetInput(0)->GetRequestedRegion().GetSize(i) );
    internalInputRegion.SetIndex( internal_i, this->GetInput(0)->GetRequestedRegion().GetIndex(i) );

    }

  ProgressReporter progress(this, 0, requestedSize[m_Dimension]);

  // allocate a vector to store internal image
  typedef typename InternalInputImageType::Pointer InternalInputImagePointer;
  std::vector< InternalInputImagePointer > internalInputs( this->GetNumberOfIndexedInputs() );

  typename InputImageType::IndexType originIndex;
  originIndex.Fill(0);
  for ( unsigned int i = 0; i < numberOfIndexedInputs; i++ )
    {
    // Passing through a N-1 direction matrix to the internal slice filter is
    // not supported to avoid dealing with singularities, but we still account
    // for the direction matrix when collapsing the origin to an N-1 point.
    typename InputImageType::PointType inputOrigin;
    this->GetInput(i)->TransformIndexToPhysicalPoint(originIndex, inputOrigin);

    InternalSpacingType internalInputSpacing;
    InternalPointType internalInputOrigin;
    unsigned int internal_dim = 0;
    for ( unsigned int dim = 0; internal_dim < InternalImageDimension; ++dim, ++internal_dim )
      {
      if ( dim == this->m_Dimension )
        {
        ++dim;
        }
      internalInputSpacing[internal_dim] = this->GetInput(i)->GetSpacing()[dim];
      internalInputOrigin[internal_dim] = inputOrigin[dim];
      }

    // keep the internal input around each iteration, because if the
    // fitlers are not run inplace, we don't need to reallocate each iteration
    internalInputs[i] = InternalInputImageType::New();

    internalInputs[i]->SetSpacing(internalInputSpacing);
    internalInputs[i]->SetOrigin(internalInputOrigin);
    }

  const IndexValueType sliceRangeMax =
    static_cast<IndexValueType>(requestedSize[m_Dimension] + requestedIndex[m_Dimension]);

  for ( IndexValueType slice = requestedIndex[m_Dimension]; slice < sliceRangeMax; ++slice )
    {
    // say to the user that we are begining a new slice
    this->m_SliceIndex = slice;
    this->InvokeEvent( IterationEvent() );

    RegionType inputRegion = this->GetInput( 0 )->GetRequestedRegion();
    inputRegion.SetIndex( m_Dimension, slice );
    inputRegion.SetSize( m_Dimension, 1 );

    // this region is the current output region we
    // are iterating on
    RegionType outputRegion = this->GetOutput( 0 )->GetRequestedRegion();
    outputRegion.SetIndex( m_Dimension, slice );
    outputRegion.SetSize( m_Dimension, 1 );

    itkDebugMacro( "inputRegion: " << inputRegion );
    itkDebugMacro( "internalInputRegion: " << internalInputRegion );

    itkDebugMacro( "outputRegion: " << outputRegion );
    itkDebugMacro( "internalOutputRegion: " << internalOutputRegion );

    itkAssertOrThrowMacro( inputRegion.GetNumberOfPixels() == internalInputRegion.GetNumberOfPixels(), "inputRegion.GetNumberOfPixels() == internalInputRegion.GetNumberOfPixel()" );
    itkAssertOrThrowMacro( outputRegion.GetNumberOfPixels() == internalOutputRegion.GetNumberOfPixels(), "outputRegion.GetNumberOfPixels() == internalOutputRegion.GetNumberOfPixel()" );

    // reallocate the internal input at each slice, so the slice by slice filter can work
    // even if the pipeline is run in place
    for ( unsigned int i = 0; i < numberOfIndexedInputs; i++ )
      {
      internalInputs[i]->SetRegions( internalInputRegion );
      internalInputs[i]->Allocate();
      m_InputFilter->SetInput(i, internalInputs[i]);

      ImageAlgorithm::Copy( this->GetInput( i ), internalInputs[i].GetPointer(), inputRegion, internalInputRegion );
      }

    // run the filter on the current slice
    this->m_InputFilter->Modified();
    this->m_OutputFilter->Modified(); // should not be needed, but may help in some cases
    this->m_OutputFilter->GetOutput()->SetRequestedRegion(internalOutputRegion);
    this->m_OutputFilter->Update();

    progress.CompletedPixel();

    // and copy the output slice to the output image
    for ( unsigned int i = 0; i < numberOfIndexedOutputs; i++ )
      {
      ImageAlgorithm::Copy( this->m_OutputFilter->GetOutput( i ), this->GetOutput( i ), internalOutputRegion, outputRegion );
      }
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Dimension: " << this->m_Dimension << std::endl;
  os << indent << "InputFilter: " << this->m_InputFilter->GetNameOfClass()
     << " " << this->m_InputFilter.GetPointer() << std::endl;
  os << indent << "OutputFilter: " << this->m_OutputFilter->GetNameOfClass()
     << " " << this->m_OutputFilter.GetPointer() << std::endl;
  os << indent << "SliceIndex: " << m_SliceIndex << std::endl;
}
}

#endif
<commit_msg>BUG: Use input RequestedRegion Index in SliceBySliceImageFilter internal.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef __itkSliceBySliceImageFilter_hxx
#define __itkSliceBySliceImageFilter_hxx

#include "itkSliceBySliceImageFilter.h"
#include "itkProgressReporter.h"
#include "itkImageAlgorithm.h"

namespace itk
{
template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SliceBySliceImageFilter()
{
  m_InputFilter = ITK_NULLPTR;
  m_OutputFilter = ITK_NULLPTR;
  this->m_Dimension = ImageDimension - 1;
  m_SliceIndex = 0;
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::VerifyInputInformation()
{

  Superclass::VerifyInputInformation();

  // verify sane parameter
  if ( this->m_Dimension >= RegionType::ImageDimension )
    {
    itkExceptionMacro("Dimension selected for slicing is greater than ImageDimension");
    }

  if ( !m_InputFilter )
    {
    itkExceptionMacro("InputFilter must be set.");
    }

  if ( !m_OutputFilter )
    {
    itkExceptionMacro("OutputFilter must be set.");
    }

}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::GenerateInputRequestedRegion()
{
  // call the superclass's implementation of this method, which
  // propagates the output requested region to all inputs
  Superclass::GenerateInputRequestedRegion();

  InputDataObjectIterator it( this );
  InputImageType * input  = dynamic_cast< InputImageType * >( it.GetInput() );

  const RegionType &requestedInputRegion = input->GetRequestedRegion();

  // The requested region is the largest in all but the slice
  // dimension. In that dimension we can stream the requested
  // slices.
  RegionType inputRegion = input->GetLargestPossibleRegion();
  inputRegion.SetIndex( m_Dimension, requestedInputRegion.GetIndex(m_Dimension) );
  inputRegion.SetSize( m_Dimension, requestedInputRegion.GetSize(m_Dimension) );

  // Use the same requested region for each input, if an input image
  // is a different size and can't fulfill the request,
  // DataObject::PropagateRequestedRegion with throw
  while( !it.IsAtEnd() )
    {
    // get pointers to the input and output
    input  = dynamic_cast< InputImageType * >( it.GetInput() );

    if (input)
      {
      input->SetRequestedRegion( inputRegion );
      }
    ++it;
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetFilter(InputFilterType *filter)
{
  OutputFilterType *outputFilter = dynamic_cast< OutputFilterType * >( filter );

  if ( outputFilter == ITK_NULLPTR && filter != ITK_NULLPTR )
    {
    // TODO: can it be replaced by a concept check ?
    itkExceptionMacro(
      "Wrong output filter type. Use SetOutputFilter() and SetInputFilter() instead of SetFilter() when input and output filter types are different.");
    }
  this->SetInputFilter(filter);
  this->SetOutputFilter(outputFilter);
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetInputFilter(InputFilterType *filter)
{
  if ( !filter )
    {
    itkExceptionMacro("InputFilter cannot be NULL.");
    }

  if ( m_InputFilter.GetPointer() != filter )
    {
    this->Modified();
    m_InputFilter = filter;
    // adapt the number of inputs and outputs
    this->SetNumberOfRequiredInputs( filter->GetNumberOfValidRequiredInputs() );
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::SetOutputFilter(OutputFilterType *filter)
{
  if ( !filter )
    {
    itkExceptionMacro("OutputFilter cannot be NULL.");
    }

  if ( m_OutputFilter.GetPointer() != filter )
    {
    this->Modified();
    m_OutputFilter = filter;
    // adapt the number of inputs and outputs
    this->SetNumberOfRequiredOutputs( filter->GetNumberOfIndexedOutputs() );
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::GenerateData()
{

  const ProcessObject::DataObjectPointerArraySizeType numberOfIndexedInputs = this->GetNumberOfIndexedInputs();
  const ProcessObject::DataObjectPointerArraySizeType numberOfIndexedOutputs = this->GetNumberOfIndexedOutputs();

  this->AllocateOutputs();

  const RegionType requestedRegion = this->GetOutput( 0 )->GetRequestedRegion();
  const IndexType requestedIndex = requestedRegion.GetIndex();
  const SizeType requestedSize = requestedRegion.GetSize();

  InternalRegionType internalOutputRegion;
  InternalRegionType internalInputRegion;

  // copy the requested region to the internal slice region in
  // dimension order
  unsigned int internal_i = 0;
  for ( unsigned int i = 0; internal_i < InternalImageDimension; ++i, ++internal_i )
    {
    if ( i == this->m_Dimension )
      {
      ++i;
      }
    internalOutputRegion.SetSize( internal_i, requestedSize[i] );
    internalOutputRegion.SetIndex( internal_i, requestedIndex[i] );

    internalInputRegion.SetSize( internal_i, this->GetInput(0)->GetRequestedRegion().GetSize(i) );
    internalInputRegion.SetIndex( internal_i, this->GetInput(0)->GetRequestedRegion().GetIndex(i) );

    }

  ProgressReporter progress(this, 0, requestedSize[m_Dimension]);

  // allocate a vector to store internal image
  typedef typename InternalInputImageType::Pointer InternalInputImagePointer;
  std::vector< InternalInputImagePointer > internalInputs( this->GetNumberOfIndexedInputs() );

  for ( unsigned int i = 0; i < numberOfIndexedInputs; i++ )
    {
    // Passing through a N-1 direction matrix to the internal slice filter is
    // not supported to avoid dealing with singularities, but we still account
    // for the direction matrix when collapsing the origin to an N-1 point.
    const typename InputImageType::IndexType originIndex = this->GetInput(i)->GetRequestedRegion().GetIndex();
    typename InputImageType::PointType inputOrigin;
    this->GetInput(i)->TransformIndexToPhysicalPoint(originIndex, inputOrigin);

    InternalSpacingType internalInputSpacing;
    InternalPointType internalInputOrigin;
    unsigned int internalDim = 0;
    for ( unsigned int dim = 0; internalDim < InternalImageDimension; ++dim, ++internalDim )
      {
      if ( dim == this->m_Dimension )
        {
        ++dim;
        }
      internalInputSpacing[internalDim] = this->GetInput(i)->GetSpacing()[dim];
      internalInputOrigin[internalDim] = inputOrigin[dim];
      }

    // keep the internal input around each iteration, because if the
    // filters are not run inplace, we don't need to reallocate each iteration
    internalInputs[i] = InternalInputImageType::New();

    internalInputs[i]->SetSpacing(internalInputSpacing);
    internalInputs[i]->SetOrigin(internalInputOrigin);
    }

  const IndexValueType sliceRangeMax =
    static_cast<IndexValueType>(requestedSize[m_Dimension] + requestedIndex[m_Dimension]);

  for ( IndexValueType slice = requestedIndex[m_Dimension]; slice < sliceRangeMax; ++slice )
    {
    // say to the user that we are begining a new slice
    this->m_SliceIndex = slice;
    this->InvokeEvent( IterationEvent() );

    RegionType inputRegion = this->GetInput( 0 )->GetRequestedRegion();
    inputRegion.SetIndex( m_Dimension, slice );
    inputRegion.SetSize( m_Dimension, 1 );

    // this region is the current output region we
    // are iterating on
    RegionType outputRegion = this->GetOutput( 0 )->GetRequestedRegion();
    outputRegion.SetIndex( m_Dimension, slice );
    outputRegion.SetSize( m_Dimension, 1 );

    itkDebugMacro( "inputRegion: " << inputRegion );
    itkDebugMacro( "internalInputRegion: " << internalInputRegion );

    itkDebugMacro( "outputRegion: " << outputRegion );
    itkDebugMacro( "internalOutputRegion: " << internalOutputRegion );

    itkAssertOrThrowMacro( inputRegion.GetNumberOfPixels() == internalInputRegion.GetNumberOfPixels(), "inputRegion.GetNumberOfPixels() == internalInputRegion.GetNumberOfPixel()" );
    itkAssertOrThrowMacro( outputRegion.GetNumberOfPixels() == internalOutputRegion.GetNumberOfPixels(), "outputRegion.GetNumberOfPixels() == internalOutputRegion.GetNumberOfPixel()" );

    // reallocate the internal input at each slice, so the slice by slice filter can work
    // even if the pipeline is run in place
    for ( unsigned int i = 0; i < numberOfIndexedInputs; i++ )
      {
      internalInputs[i]->SetRegions( internalInputRegion );
      internalInputs[i]->Allocate();
      m_InputFilter->SetInput(i, internalInputs[i]);

      ImageAlgorithm::Copy( this->GetInput( i ), internalInputs[i].GetPointer(), inputRegion, internalInputRegion );
      }

    // run the filter on the current slice
    this->m_InputFilter->Modified();
    this->m_OutputFilter->Modified(); // should not be needed, but may help in some cases
    this->m_OutputFilter->GetOutput()->SetRequestedRegion(internalOutputRegion);
    this->m_OutputFilter->Update();

    progress.CompletedPixel();

    // and copy the output slice to the output image
    for ( unsigned int i = 0; i < numberOfIndexedOutputs; i++ )
      {
      ImageAlgorithm::Copy( this->m_OutputFilter->GetOutput( i ), this->GetOutput( i ), internalOutputRegion, outputRegion );
      }
    }
}

template< typename TInputImage, typename TOutputImage, typename TInputFilter, typename TOutputFilter, typename TInternalInputImageType,
          typename TInternalOutputImageType >
void
SliceBySliceImageFilter< TInputImage, TOutputImage, TInputFilter, TOutputFilter, TInternalInputImageType,
                         TInternalOutputImageType >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);

  os << indent << "Dimension: " << this->m_Dimension << std::endl;
  os << indent << "InputFilter: " << this->m_InputFilter->GetNameOfClass()
     << " " << this->m_InputFilter.GetPointer() << std::endl;
  os << indent << "OutputFilter: " << this->m_OutputFilter->GetNameOfClass()
     << " " << this->m_OutputFilter.GetPointer() << std::endl;
  os << indent << "SliceIndex: " << m_SliceIndex << std::endl;
}
}

#endif
<|endoftext|>