<commit_before>#include <cstdio>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <include/grassmann_pca_with_trimming.hpp>
#include <include/private/boost_ublas_external_storage.hpp>
#include <include/private/boost_ublas_row_iterator.hpp>

#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>

#include <boost/iterator/iterator_facade.hpp>

#include <string>
#include <fstream>

static std::string movielocation = "/is/ps/shared/users/jonas/movies/";
static std::string eigenvectorslocation = "./";

void number2filename(size_t file_number, char *filename)
{
  const char *fn_template = (movielocation + "starwars_%.3u/frame%.7u.png").c_str();
  const size_t dir_num = file_number / 10000;
  sprintf(filename, fn_template, dir_num, file_number);
}

//! An container over the content of a cvMat, addressable
//! in a vector fashion.
template <class T>
struct cvMatAsVector
{
  cvMatAsVector(const cv::Mat& image_) :
    image(image_),
    width(image_.size().width),
    height(image_.size().height)
  {}

  T operator()(std::size_t index) const
  {
    int colorchannel = index % 3;
    index /= 3;
    int column = index % width;
    index /= width;
    return image.at<cv::Vec3b>(index, column)[colorchannel];
  }

  struct internal_iterator
  {
    cvMatAsVector<T> &outer_instance;

    internal_iterator() : current_index(0){}
    internal_iterator(size_t index) : current_index(index) {}

    T const& operator*() const
    {
      return outer_instance[current_index];
    }

    internal_iterator& operator++()
    {
      current_index++;
      return *this;
    }

    size_t current_index;
  };

  internal_iterator begin() const
  {
    return internal_iterator(0);
  }

  internal_iterator end() const
  {
    return internal_iterator(size());
  }

  size_t size() const
  {
    return width * height * 3;
  }

  const cv::Mat& image;
  const size_t width;
  const size_t height;

};

//! An iterator that will load the images on demand instead of storing everything on memory
template <class T>
class iterator_on_image_files :
  public boost::iterator_facade<
        iterator_on_image_files<T>
      , boost::numeric::ublas::vector<T>
      , std::random_access_iterator_tag
      , boost::numeric::ublas::vector<T> const& // const reference
    >
{
public:
  typedef iterator_on_image_files<T> this_type;
  typedef boost::numeric::ublas::vector<T> image_vector_type;
  iterator_on_image_files() : m_index(std::numeric_limits<size_t>::max())
  {}

  explicit iterator_on_image_files(size_t index)
    : m_index(index)
  {}

private:
  friend class boost::iterator_core_access;

  typename this_type::difference_type distance_to(this_type const& r) const
  {
    return typename this_type::difference_type(r.m_index) - typename this_type::difference_type(m_index); // sign promotion
  }

  void increment()
  {
    m_index++;
    image_vector.clear();
  }

  bool equal(this_type const& other) const
  {
    return this->m_index == other.m_index;
  }

  image_vector_type const& dereference() const
  {
    if(image_vector.empty())
    {
      read_image();
    }
    return image_vector;
  }

  void read_image() const
  {
    char filename[MAX_PATH];
    number2filename(m_index, filename);
    std::cout << "Reading " << filename << std::endl;
    cv::Mat image = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
    if(!image.data)
    {
      std::ostringstream o;
      o << "error: could not load image '" << filename << "'";
      std::cerr << o.str() << std::endl;
      throw std::runtime_error(o.str());
    }

    const int w = image.size().width;
    const int h = image.size().height;

    image_vector.resize(w * h * 3);
    typename boost::numeric::ublas::vector<T>::iterator it = image_vector.begin();

    for(int y = 0; y < h; y++)
    {
      for(int x = 0; x < w; x++)
      {
        cv::Vec3b pixel = image.at<cv::Vec3b>(y, x);
        *it++ = pixel[0];
        *it++ = pixel[1];
        *it++ = pixel[2];
      }
    }
  }

  void advance(typename this_type::difference_type n)
  {
    if(n < 0)
    {
      assert((-n) <= static_cast<typename this_type::difference_type>(m_index));
      m_index -= n;
    }
    else
    {
      //assert(n + index <= matrix->size1());
      m_index += n;
    }
    if(n != 0)
    {
      image_vector.clear();
    }
  }

  size_t m_index;
  mutable boost::numeric::ublas::vector<T> image_vector;
};

//! An output vector that also writes to a file
template <class data_iterator_t>
class iterator_on_output_data :
  public boost::iterator_facade<
        iterator_on_output_data<data_iterator_t>
      , typename data_iterator_t::value_type
      , std::random_access_iterator_tag
      , typename data_iterator_t::reference
    >
{

public:
  typedef typename data_iterator_t::reference reference;
  typedef iterator_on_output_data<data_iterator_t> this_type;

  iterator_on_output_data() :
    m_index(std::numeric_limits<size_t>::max()),
    m_max_element_per_line(100),
    internal_it()
  {}

  explicit iterator_on_output_data(size_t index, data_iterator_t it_) :
    m_index(index),
    m_max_element_per_line(100),
    internal_it(it_)
  {}

  void save_eigenvector()
  {
    char filename[MAX_PATH];
    const char * eigen_vector_template = "eigenvector_%.7d.txt";
    sprintf(filename, eigen_vector_template, m_index);

    std::ofstream f(filename);
    if(!f.is_open())
    {
      std::cerr << "Cannot open the file " << filename << " for writing" << std::endl;
      return;
    }

    std::cout << "Writing eigenvector file " << filename << std::endl;

    typedef typename data_iterator_t::value_type::iterator element_iterator;

    element_iterator itelement(internal_it->begin());
    for(int i = 0; i < internal_it->size(); i++, ++itelement)
    {
      if((i + 1) % m_max_element_per_line == 0)
      {
        f << std::endl;
      }

      f << *itelement;
    }

    f.close();
    std::cout << "Writing eigenvector file " << filename << " -- ok " << std::endl;
  }

private:
  friend class boost::iterator_core_access;

  typename this_type::difference_type distance_to(this_type const& r) const
  {
    return typename this_type::difference_type(r.m_index) - typename this_type::difference_type(m_index); // sign promotion
  }

  void increment() {
    // here we save before going further, except if it has not been changed
    save_eigenvector();
    m_index++;
    ++internal_it;
  }

  void advance(typename this_type::difference_type n)
  {
    if(n < 0)
    {
      assert((-n) <= static_cast<typename this_type::difference_type>(m_index));
      m_index -= n;
    }
    else
    {
      //assert(n + index <= matrix->size1());
      m_index += n;
    }

  }

  bool equal(this_type const& other) const
  {
    return this->internal_it == other.internal_it;
  }

  reference dereference() const
  {
    return *internal_it;
  }

  size_t m_index;
  // max number of element on one line during the save
  size_t m_max_element_per_line;
  data_iterator_t internal_it;
};

#if 0
template <class data_t>
class data_and_save : data_t
{
  size_t index;

  //! sets the index that will determine the filename to which this eigenvector will
  //! be saved.
  void set_index(size_t index_)
  {
    index = index_;
  }

  data_t& operator*()
};
#endif

int main(int argc, char *argv[])
{
  namespace po = boost::program_options;

  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("nb-frames,f",       po::value<int>(),           "number of frames in the movie")
    ("movie,m",           po::value<std::string>(),   "full path to the movie location")
    ("max-dimensions,d",  po::value<int>(),           "requested number of components for the computation of the trimmed grassmann average")
    ("max-iterations",    po::value<int>(),           "maximum number of iterations (defaults to the number of frames)")
    ("nb-pca-steps",      po::value<int>(),           "number of pca steps")
    ("trimming-percentage",      po::value<float>(),  "percentage of trimming")
    ("nb-processors",      po::value<int>(),          "number of processors used (defaults to 1)")
  ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if(vm.count("help"))
  {
    std::cout << desc << "\n";
    return 1;
  }

  if(!vm.count("trimming-percentage"))
  {
    std::cerr << "the parameter 'trimming-percentage' should be set, now exiting...\n";
    return 1;
  }
  const float trimming_percentage = vm["trimming-percentage"].as<float>();

  size_t num_frames = 100; //179415;
  if(vm.count("nb-frames"))
  {
    std::cout << "The movie contains #" << vm["nb-frames"].as<int>() << " frames.\n";
    num_frames = vm["nb-frames"].as<int>();
  }
  else
  {
    std::cout << "Nb of frames not set, setting it to" << num_frames << "\n";
  }

  size_t max_dimension = 30;
  if(vm.count("max-dimensions"))
  {
    std::cout << "Number of components requested #" << vm["max-dimensions"].as<int>() << "\n";
    max_dimension = vm["max-dimensions"].as<int>();
  }
  else
  {
    std::cout << "Nb of components not set, setting it to" << max_dimension << "\n";
  }

  size_t max_iterations = num_frames;
  if(vm.count("max-iterations"))
  {
    std::cout << "Maximum number of iterations #" << vm["max-iterations"].as<int>() << "\n";
    max_iterations = vm["max-iterations"].as<int>();
  }

  size_t nb_pca_steps = 3;
  if(vm.count("nb-pca-steps"))
  {
    std::cout << "Number of PCA steps #" << vm["nb-pca-steps"].as<int>() << "\n";
    nb_pca_steps = vm["nb-pca-steps"].as<int>();
  }
  else
  {
    std::cout << "Number of PCA steps not set, setting it to" << nb_pca_steps << "\n";
  }

  int nb_processors = 0;
  if(vm.count("nb-processors"))
  {
    std::cout << "Number of processors #" << vm["nb-processors"].as<int>() << "\n";
    nb_processors = vm["nb-processors"].as<int>();
  }

  size_t rows(0);
  size_t cols(0);

  {
    char filename[MAX_PATH];
    // Read first image to get image size
    number2filename(1, filename);

    cv::Mat image = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
    cv::Size image_size = image.size();
    rows = image_size.height;
    cols = image_size.width;
  }

  // Allocate data
  std::cout << "=== Allocate ===" << std::endl;
  std::cout << "  Number of images: " << num_frames << std::endl;
  std::cout << "  Image size:       " << cols << "x" << rows << " (RGB)" << std::endl;
  std::cout << "  Data size:        " << (num_frames*rows*cols * 3) / (1024 * 1024) << " MB" << std::endl;

  iterator_on_image_files<float> iterator_file_begin(1);
  iterator_on_image_files<float> iterator_file_end(num_frames + 1);

  // Compute trimmed Grassmann Average
  // XXX: Ask Raffi for help here
  // XXX: We need to time this computation

  namespace ub = boost::numeric::ublas;

  // type for the final eigen vectors
  typedef ub::vector<double> data_t;

  using namespace grassmann_averages_pca;
  using namespace grassmann_averages_pca::details::ublas_helpers;

  typedef double input_array_type;

  const size_t dimension = rows * cols;
  const size_t nb_elements = num_frames;

  // this is the form of the data extracted from the storage
  typedef ub::vector<input_array_type> data_t;
  typedef grassmann_pca_with_trimming< data_t > grassmann_pca_with_trimming_t;

  // main instance
  grassmann_pca_with_trimming_t instance(trimming_percentage / 100);

  typedef std::vector<data_t> output_eigenvector_collection_t;
  output_eigenvector_collection_t v_output_eigenvectors(nb_elements);

  if(nb_processors > 0)
  {
    if(!instance.set_nb_processors(nb_processors))
    {
      std::cerr << "[configuration]" << "Incorrect number of processors. Please consult the documentation (was " << nb_processors << ")" << std::endl;
      return 1;
    }
  }

  if(!instance.set_nb_steps_pca(nb_pca_steps))
  {
    std::cerr << "[configuration]" << "Incorrect number of regular PCA steps. Please consult the documentation (was " << nb_pca_steps << ")" << std::endl;
    return false;
  }

  bool ret = instance.batch_process(
    max_iterations,
    max_dimension,
    iterator_file_begin,
    iterator_file_end,
    iterator_on_output_data<output_eigenvector_collection_t::iterator>(0, v_output_eigenvectors.begin()));

  // Save resulting components
  // XXX: Ask Raffi for help here

  return 0;
}

<commit_msg>small changes and cleanup now all float instead of double<commit_after>#include <cstdio>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <include/grassmann_pca_with_trimming.hpp>
#include <include/private/boost_ublas_external_storage.hpp>
#include <include/private/boost_ublas_row_iterator.hpp>

#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>

#include <boost/iterator/iterator_facade.hpp>

#include <string>
#include <fstream>

#ifndef MAX_PATH
  // "funny" differences win32/posix
  #define MAX_PATH PATH_MAX
#endif

static std::string movielocation = "/is/ps/shared/users/jonas/movies/";
static std::string eigenvectorslocation = "./";

void number2filename(size_t file_number, char *filename)
{
  const char *fn_template = (movielocation + "starwars_%.3u/frame%.7u.png").c_str();
  const size_t dir_num = file_number / 10000;
  sprintf(filename, fn_template, dir_num, file_number);
}

//! An iterator that will load the images on demand instead of storing everything on memory
template <class T>
class iterator_on_image_files :
  public boost::iterator_facade<
        iterator_on_image_files<T>
      , boost::numeric::ublas::vector<T>
      , std::random_access_iterator_tag
      , boost::numeric::ublas::vector<T> const& // const reference
    >
{
public:
  typedef iterator_on_image_files<T> this_type;
  typedef boost::numeric::ublas::vector<T> image_vector_type;
  iterator_on_image_files() : m_index(std::numeric_limits<size_t>::max())
  {}

  explicit iterator_on_image_files(size_t index)
    : m_index(index)
  {}

private:
  friend class boost::iterator_core_access;

  typename this_type::difference_type distance_to(this_type const& r) const
  {
    return typename this_type::difference_type(r.m_index) - typename this_type::difference_type(m_index); // sign promotion
  }

  void increment()
  {
    m_index++;
    image_vector.clear();
  }

  bool equal(this_type const& other) const
  {
    return this->m_index == other.m_index;
  }

  image_vector_type const& dereference() const
  {
    if(image_vector.empty())
    {
      read_image();
    }
    return image_vector;
  }

  void read_image() const
  {
    char filename[MAX_PATH];
    number2filename(m_index, filename);
    std::cout << "Reading " << filename << std::endl;
    cv::Mat image = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
    if(!image.data)
    {
      std::ostringstream o;
      o << "error: could not load image '" << filename << "'";
      std::cerr << o.str() << std::endl;
      throw std::runtime_error(o.str());
    }

    const int w = image.size().width;
    const int h = image.size().height;

    image_vector.resize(w * h * 3);
    typename boost::numeric::ublas::vector<T>::iterator it = image_vector.begin();

    for(int y = 0; y < h; y++)
    {
      for(int x = 0; x < w; x++)
      {
        cv::Vec3b pixel = image.at<cv::Vec3b>(y, x);
        *it++ = pixel[0];
        *it++ = pixel[1];
        *it++ = pixel[2];
      }
    }
  }

  void advance(typename this_type::difference_type n)
  {
    if(n < 0)
    {
      assert((-n) <= static_cast<typename this_type::difference_type>(m_index));
      m_index -= n;
    }
    else
    {
      //assert(n + index <= matrix->size1());
      m_index += n;
    }
    if(n != 0)
    {
      image_vector.clear();
    }
  }

  size_t m_index;
  mutable boost::numeric::ublas::vector<T> image_vector;
};

//! An output vector that also writes to a file
template <class data_iterator_t>
class iterator_on_output_data :
  public boost::iterator_facade<
        iterator_on_output_data<data_iterator_t>
      , typename data_iterator_t::value_type
      , std::random_access_iterator_tag
      , typename data_iterator_t::reference
    >
{

public:
  typedef typename data_iterator_t::reference reference;
  typedef iterator_on_output_data<data_iterator_t> this_type;

  iterator_on_output_data() :
    m_index(std::numeric_limits<size_t>::max()),
    m_max_element_per_line(100),
    internal_it()
  {}

  explicit iterator_on_output_data(size_t index, data_iterator_t it_) :
    m_index(index),
    m_max_element_per_line(100),
    internal_it(it_)
  {}

  void save_eigenvector()
  {
    char filename[MAX_PATH];
    const char * eigen_vector_template = "eigenvector_%.7d.txt";
    sprintf(filename, eigen_vector_template, m_index);

    std::ofstream f(filename);
    if(!f.is_open())
    {
      std::cerr << "Cannot open the file " << filename << " for writing" << std::endl;
      return;
    }

    std::cout << "Writing eigenvector file " << filename << std::endl;

    typedef typename data_iterator_t::value_type::iterator element_iterator;

    element_iterator itelement(internal_it->begin());
    for(int i = 0; i < internal_it->size(); i++, ++itelement)
    {
      if((i + 1) % m_max_element_per_line == 0)
      {
        f << std::endl;
      }

      f << *itelement;
    }

    f.close();
    std::cout << "Writing eigenvector file " << filename << " -- ok " << std::endl;
  }

private:
  friend class boost::iterator_core_access;

  typename this_type::difference_type distance_to(this_type const& r) const
  {
    return typename this_type::difference_type(r.m_index) - typename this_type::difference_type(m_index); // sign promotion
  }

  void increment() {
    // here we save before going further, except if it has not been changed
    save_eigenvector();
    m_index++;
    ++internal_it;
  }

  void advance(typename this_type::difference_type n)
  {
    if(n < 0)
    {
      assert((-n) <= static_cast<typename this_type::difference_type>(m_index));
      m_index -= n;
    }
    else
    {
      //assert(n + index <= matrix->size1());
      m_index += n;
    }

  }

  bool equal(this_type const& other) const
  {
    return this->internal_it == other.internal_it;
  }

  reference dereference() const
  {
    return *internal_it;
  }

  size_t m_index;
  // max number of element on one line during the save
  size_t m_max_element_per_line;
  data_iterator_t internal_it;
};

int main(int argc, char *argv[])
{
  namespace po = boost::program_options;

  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("nb-frames,f",       po::value<int>(),           "number of frames in the movie")
    ("movie,m",           po::value<std::string>(),   "full path to the movie location")
    ("max-dimensions,d",  po::value<int>(),           "requested number of components for the computation of the trimmed grassmann average")
    ("max-iterations",    po::value<int>(),           "maximum number of iterations (defaults to the number of frames)")
    ("nb-pca-steps",      po::value<int>(),           "number of pca steps")
    ("trimming-percentage",      po::value<float>(),  "percentage of trimming")
    ("nb-processors",      po::value<int>(),          "number of processors used (defaults to 1)")
  ;

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if(vm.count("help"))
  {
    std::cout << desc << "\n";
    return 1;
  }

  if(!vm.count("trimming-percentage"))
  {
    std::cerr << "the parameter 'trimming-percentage' should be set, now exiting...\n";
    return 1;
  }
  const float trimming_percentage = vm["trimming-percentage"].as<float>();

  size_t num_frames = 100; //179415;
  if(vm.count("nb-frames"))
  {
    std::cout << "The movie contains #" << vm["nb-frames"].as<int>() << " frames.\n";
    num_frames = vm["nb-frames"].as<int>();
  }
  else
  {
    std::cout << "Nb of frames not set, setting it to" << num_frames << "\n";
  }

  if(vm.count("movie"))
  {
    std::cout << "Directory of the movie #" << vm["movie"].as<std::string>() << "\n";
    movielocation = vm["movie"].as<std::string>();
  }

  size_t max_dimension = 30;
  if(vm.count("max-dimensions"))
  {
    std::cout << "Number of components requested #" << vm["max-dimensions"].as<int>() << "\n";
    max_dimension = vm["max-dimensions"].as<int>();
  }
  else
  {
    std::cout << "Nb of components not set, setting it to" << max_dimension << "\n";
  }

  size_t max_iterations = num_frames;
  if(vm.count("max-iterations"))
  {
    std::cout << "Maximum number of iterations #" << vm["max-iterations"].as<int>() << "\n";
    max_iterations = vm["max-iterations"].as<int>();
  }

  size_t nb_pca_steps = 3;
  if(vm.count("nb-pca-steps"))
  {
    std::cout << "Number of PCA steps #" << vm["nb-pca-steps"].as<int>() << "\n";
    nb_pca_steps = vm["nb-pca-steps"].as<int>();
  }
  else
  {
    std::cout << "Number of PCA steps not set, setting it to" << nb_pca_steps << "\n";
  }

  int nb_processors = 0;
  if(vm.count("nb-processors"))
  {
    std::cout << "Number of processors #" << vm["nb-processors"].as<int>() << "\n";
    nb_processors = vm["nb-processors"].as<int>();
  }

  size_t rows(0);
  size_t cols(0);

  {
    char filename[MAX_PATH];
    // Read first image to get image size
    number2filename(1, filename);

    cv::Mat image = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
    cv::Size image_size = image.size();
    rows = image_size.height;
    cols = image_size.width;
  }

  // Allocate data
  std::cout << "=== Allocate ===" << std::endl;
  std::cout << "  Number of images: " << num_frames << std::endl;
  std::cout << "  Image size:       " << cols << "x" << rows << " (RGB)" << std::endl;
  std::cout << "  Data size:        " << (num_frames*rows*cols * 3) / (1024 * 1024) << " MB" << std::endl;

  iterator_on_image_files<float> iterator_file_begin(1);
  iterator_on_image_files<float> iterator_file_end(num_frames + 1);

  // Compute trimmed Grassmann Average
  // XXX: Ask Raffi for help here
  // XXX: We need to time this computation

  namespace ub = boost::numeric::ublas;
  using namespace grassmann_averages_pca;
  using namespace grassmann_averages_pca::details::ublas_helpers;

  // type of the scalars manipulated by the algorithm
  typedef float input_array_type;

  //const size_t dimension = rows * cols;
  const size_t nb_elements = num_frames;

  // this is the form of the data extracted from the storage
  typedef ub::vector<input_array_type> data_t;
  typedef grassmann_pca_with_trimming< data_t > grassmann_pca_with_trimming_t;

  // main instance
  grassmann_pca_with_trimming_t instance(trimming_percentage / 100);

  typedef std::vector<data_t> output_eigenvector_collection_t;
  output_eigenvector_collection_t v_output_eigenvectors(nb_elements);

  if(nb_processors > 0)
  {
    if(!instance.set_nb_processors(nb_processors))
    {
      std::cerr << "[configuration]" << "Incorrect number of processors. Please consult the documentation (was " << nb_processors << ")" << std::endl;
      return 1;
    }
  }

  if(!instance.set_nb_steps_pca(nb_pca_steps))
  {
    std::cerr << "[configuration]" << "Incorrect number of regular PCA steps. Please consult the documentation (was " << nb_pca_steps << ")" << std::endl;
    return false;
  }

  bool ret = instance.batch_process(
    max_iterations,
    max_dimension,
    iterator_file_begin,
    iterator_file_end,
    iterator_on_output_data<output_eigenvector_collection_t::iterator>(0, v_output_eigenvectors.begin()));

  // Save resulting components
  // XXX: Ask Raffi for help here

  if(!ret)
  {
    std::cerr << "The process returned an error" << std::endl;
    return 1;
  }

  return 0;
}

<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include <rapidcheck/gtest.h>

#include <string>

// http://www.programcreek.com/2013/02/longest-substring-which-contains-2-unique-characters/
// Given a string, find the longest substring that contains only two unique characters.
// For example, given "abcbbbbcccbdddadacb", the longest substring that contains 2 unique character is "bcbbbbcccb".

// Algorithm to be tested:
// std::size_t longest_size(std::string const& in);

// Running tests

TEST(TEST_NAME, EmptyString)
{
  ASSERT_EQ(0, longest_size(""));
}

TEST(TEST_NAME, UniqueCharacter)
{
  ASSERT_EQ(5, longest_size("aaaaa"));
}

TEST(TEST_NAME, TwoCharacters)
{
  ASSERT_EQ(7, longest_size("abbaaba"));
}

TEST(TEST_NAME, SubstringOfMainString)
{
  ASSERT_EQ(10, longest_size("abcbbbbcccbdddadacb"));
}

RC_GTEST_PROP(TEST_NAME, RandomData, (char c1, char c2))
{
  RC_PRE(c1 != c2);

  std::string answer_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(rc::gen::element<char>(char(c1), char(c2))))
    .as("longest part with 2 different chars");
  RC_PRE(answer_str.find(c1) != std::string::npos);
  RC_PRE(answer_str.find(c2) != std::string::npos);

  std::size_t pre_length = *rc::gen::inRange<std::size_t>(0, answer_str.size())
    .as("length for the part before longest");
  std::string pre_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(pre_length, rc::gen::arbitrary<char>()))
    .as("before longest chars");
  RC_PRE(pre_str.size() == std::size_t() || (pre_str.back() != c1 && pre_str.back() != c2));
  RC_PRE(pre_str.size() < std::size_t(2) || pre_str[pre_str.size() -1] != pre_str[pre_str.size() -2]);

  std::size_t post_length = *rc::gen::inRange<std::size_t>(0, answer_str.size())
    .as("length of the part after longest");
  std::string post_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(post_length, rc::gen::arbitrary<char>()))
    .as("after longest chars");
  RC_PRE(post_str.size() == std::size_t() || (post_str.front() != c1 && post_str.front() != c2));
  RC_PRE(post_str.size() < std::size_t(2) || post_str[0] != post_str[1]);

  std::string data = pre_str + answer_str + post_str;
  RC_ASSERT(answer_str.size() == longest_size(data));
}

<commit_msg>[visual studio] Fix compile issue in longest-substr-2-uniques<commit_after>#include "gtest/gtest.h"
#include <rapidcheck/gtest.h>

#include <string>

// http://www.programcreek.com/2013/02/longest-substring-which-contains-2-unique-characters/
// Given a string, find the longest substring that contains only two unique characters.
// For example, given "abcbbbbcccbdddadacb", the longest substring that contains 2 unique character is "bcbbbbcccb".

// Algorithm to be tested:
// std::size_t longest_size(std::string const& in);

// Running tests

TEST(TEST_NAME, EmptyString)
{
  ASSERT_EQ(0, longest_size(""));
}

TEST(TEST_NAME, UniqueCharacter)
{
  ASSERT_EQ(5, longest_size("aaaaa"));
}

TEST(TEST_NAME, TwoCharacters)
{
  ASSERT_EQ(7, longest_size("abbaaba"));
}

TEST(TEST_NAME, SubstringOfMainString)
{
  ASSERT_EQ(10, longest_size("abcbbbbcccbdddadacb"));
}

RC_GTEST_PROP(TEST_NAME, RandomData, (char c1, char c2))
{
  RC_PRE(c1 != c2);

  char moved_c1 = c1, moved_c2 = c2;
  std::string answer_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(rc::gen::element<char>(std::move(moved_c1), std::move(moved_c2))))
    .as("longest part with 2 different chars");
  RC_PRE(answer_str.find(c1) != std::string::npos);
  RC_PRE(answer_str.find(c2) != std::string::npos);

  std::size_t pre_length = *rc::gen::inRange<std::size_t>(0, answer_str.size())
    .as("length for the part before longest");
  std::string pre_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(pre_length, rc::gen::arbitrary<char>()))
    .as("before longest chars");
  RC_PRE(pre_str.size() == std::size_t() || (pre_str.back() != c1 && pre_str.back() != c2));
  RC_PRE(pre_str.size() < std::size_t(2) || pre_str[pre_str.size() -1] != pre_str[pre_str.size() -2]);

  std::size_t post_length = *rc::gen::inRange<std::size_t>(0, answer_str.size())
    .as("length of the part after longest");
  std::string post_str = *rc::gen::apply(
      [](auto&& vs) { return std::string(std::begin(vs), std::end(vs)); }
      , rc::gen::container<std::vector<char>>(post_length, rc::gen::arbitrary<char>()))
    .as("after longest chars");
  RC_PRE(post_str.size() == std::size_t() || (post_str.front() != c1 && post_str.front() != c2));
  RC_PRE(post_str.size() < std::size_t(2) || post_str[0] != post_str[1]);

  std::string data = pre_str + answer_str + post_str;
  RC_ASSERT(answer_str.size() == longest_size(data));
}

<|endoftext|>


<commit_before>/*!
 * \brief Short Time Fourier Transform.
 * \author Thomas Hamboeck, Austrian Kangaroos 2014
 */
#include "STFT.h"

#include <limits>
#include <complex>
#include <iostream>

//                     0, params.nWindowSize, params.nWindowSkipping, params.nWindowSizePadded, spectrumHandler
STFT::STFT(const int channelOffset, const int windowTime, const int windowTimeStep, const int windowFrequency, SpectrumHandler *handler)
    : offset(channelOffset),
      windowTime(windowTime),
      windowTimeStep(windowTimeStep),
      windowFrequency(windowFrequency),
      windowFrequencyHalf(windowFrequency / 2 + 1),
	  handler(handler),
      nOverflow(0), overflownData(NULL), input(NULL), output(NULL), outputMag(NULL)
{
    overflownData   = new int16_t[windowTime]; /* actually a max of (windowTime - 1) */
    input           = static_cast<double*>(fftw_malloc(sizeof(double) * windowFrequency));
    output          = static_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex) * windowFrequencyHalf));
    outputMag       = new double[windowFrequencyHalf];

    //WARN(windowFrequency >= windowTime, "Frequency window must be greater than Time Window.");

    for(int i = 0; i < windowFrequency; ++i) {
      input[i] = 0.0;
    }

    plan = fftw_plan_dft_r2c_1d(windowFrequency, input, output, FFTW_MEASURE);
}

STFT::~STFT()
{
    if(overflownData) {
        delete[] overflownData;
    }
    if(input) {
        fftw_free(input);
    }
    if(output) {
        fftw_free(output);
    }
    if(outputMag) {
        delete[] outputMag;
    }
    if(plan) {
        fftw_destroy_plan(plan);
    }
}

void STFT::intToFloat(const int16_t &in, double &out)
{
    out = static_cast<double>(in) / static_cast<double>(std::numeric_limits<int16_t>::max() + 1);
}

void STFT::newData(const int16_t *data, int length, short channels)
{
    int iBegin, iEnd, iDataChannel, iBuffer;

    iBuffer = 0;

    /* for each overflown data */
    while(iBuffer < nOverflow) {
        intToFloat(overflownData[iBuffer], input[iBuffer]);
        ++iBuffer;
    }

    iBegin = 0;
    while(true)
    {
        iEnd = iBegin * channels + windowTime*channels;
        if(iEnd > length) {
            break;
        }

        // copy the data fro the window

        iDataChannel = iBegin * channels + offset;
        while(iBuffer < windowTime) {
            intToFloat(data[iDataChannel], input[iBuffer]);
            ++iBuffer;
            iDataChannel += channels;
        }
        /* and the rest is zero */

        fftw_execute(plan);

        /* calc magnitude */
        for(int i = 0; i < windowFrequencyHalf; ++i) {
            outputMag[i] = std::sqrt(output[i][0]*output[i][0] + output[i][1]*output[i][1]);
        }

        if(handler != NULL) {
          handler->handle(outputMag, windowFrequencyHalf);
        }

        /* next cycle */
        iBegin  += windowTimeStep;
        iBuffer = 0;
    }

    nOverflow = 0;
    iDataChannel = iBegin * channels + offset;
    while(iDataChannel < length) {
        /* copy to overflow buffer */
        overflownData[nOverflow] = data[iDataChannel];
        ++nOverflow;
        iDataChannel += channels;
    }
}
<commit_msg>fix value overflow?<commit_after>/*!
 * \brief Short Time Fourier Transform.
 * \author Thomas Hamboeck, Austrian Kangaroos 2014
 */
#include "STFT.h"

#include <limits>
#include <complex>
#include <iostream>

//                     0, params.nWindowSize, params.nWindowSkipping, params.nWindowSizePadded, spectrumHandler
STFT::STFT(const int channelOffset, const int windowTime, const int windowTimeStep, const int windowFrequency, SpectrumHandler *handler)
    : offset(channelOffset),
      windowTime(windowTime),
      windowTimeStep(windowTimeStep),
      windowFrequency(windowFrequency),
      windowFrequencyHalf(windowFrequency / 2 + 1),
	  handler(handler),
      nOverflow(0), overflownData(NULL), input(NULL), output(NULL), outputMag(NULL)
{
    overflownData   = new int16_t[windowTime]; /* actually a max of (windowTime - 1) */
    input           = static_cast<double*>(fftw_malloc(sizeof(double) * windowFrequency));
    output          = static_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex) * windowFrequencyHalf));
    outputMag       = new double[windowFrequencyHalf];

    //WARN(windowFrequency >= windowTime, "Frequency window must be greater than Time Window.");

    for(int i = 0; i < windowFrequency; ++i) {
      input[i] = 0.0;
    }

    plan = fftw_plan_dft_r2c_1d(windowFrequency, input, output, FFTW_MEASURE);
}

STFT::~STFT()
{
    if(overflownData) {
        delete[] overflownData;
    }
    if(input) {
        fftw_free(input);
    }
    if(output) {
        fftw_free(output);
    }
    if(outputMag) {
        delete[] outputMag;
    }
    if(plan) {
        fftw_destroy_plan(plan);
    }
}

void STFT::intToFloat(const int16_t &in, double &out)
{
    out = static_cast<double>(in) / (static_cast<double>(std::numeric_limits<int16_t>::max()) + 1.0);
}

void STFT::newData(const int16_t *data, int length, short channels)
{
    int iBegin, iEnd, iDataChannel, iBuffer;

    iBuffer = 0;

    /* for each overflown data */
    while(iBuffer < nOverflow) {
        intToFloat(overflownData[iBuffer], input[iBuffer]);
        ++iBuffer;
    }

    iBegin = 0;
    while(true)
    {
        iEnd = iBegin * channels + windowTime*channels;
        if(iEnd > length) {
            break;
        }

        // copy the data fro the window

        iDataChannel = iBegin * channels + offset;
        while(iBuffer < windowTime) {
            intToFloat(data[iDataChannel], input[iBuffer]);
            ++iBuffer;
            iDataChannel += channels;
        }
        /* and the rest is zero */

        fftw_execute(plan);

        /* calc magnitude */
        for(int i = 0; i < windowFrequencyHalf; ++i) {
            outputMag[i] = std::sqrt(output[i][0]*output[i][0] + output[i][1]*output[i][1]);
        }

        if(handler != NULL) {
          handler->handle(outputMag, windowFrequencyHalf);
        }

        /* next cycle */
        iBegin  += windowTimeStep;
        iBuffer = 0;
    }

    nOverflow = 0;
    iDataChannel = iBegin * channels + offset;
    while(iDataChannel < length) {
        /* copy to overflow buffer */
        overflownData[nOverflow] = data[iDataChannel];
        ++nOverflow;
        iDataChannel += channels;
    }
}
<|endoftext|>


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

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

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 <vtkObjectFactory.h>

// MRML includes
#include "vtkMRMLSpatialObjectsStorageNode.h"
#include "vtkMRMLSpatialObjectsNode.h"
#include "vtkMRMLSpatialObjectsDisplayNode.h"

// VTK includes
#include <vtkAppendPolyData.h>
#include <vtkCellArray.h>
#include <vtkCleanPolyData.h>
#include <vtkDoubleArray.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyLine.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkStringArray.h>

// ITK includes
#include <itkTubeSpatialObject.h>
#include <itkSpatialObjectReader.h>
#include <itkSpatialObjectWriter.h>

//------------------------------------------------------------------------------
vtkMRMLNodeNewMacro(vtkMRMLSpatialObjectsStorageNode);

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//------------------------------------------------------------------------------
bool vtkMRMLSpatialObjectsStorageNode::
CanReadInReferenceNode(vtkMRMLNode *refNode)
{
  return refNode->IsA("vtkMRMLSpatialObjectsNode");
}

//------------------------------------------------------------------------------
int vtkMRMLSpatialObjectsStorageNode::ReadDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLSpatialObjectsNode* spatialObjectsNode =
    vtkMRMLSpatialObjectsNode::SafeDownCast(refNode);

  if(Superclass::ReadDataInternal(refNode) != 0)
    {
    return 0;
    }

  std::string fullName = this->GetFullNameFromFileName();
  if(fullName == std::string(""))
    {
    vtkErrorMacro("ReadData: File name not specified");
    return 0;
    }

  // compute file prefix
  std::string name(fullName);
  std::string::size_type loc = name.find_last_of(".");
  if( loc == std::string::npos )
    {
    vtkErrorMacro("ReadData: no file extension specified: " << name.c_str());
    return 0;
    }
  std::string extension = name.substr(loc);
  vtkDebugMacro("ReadData: extension = " << extension.c_str());

  int result = 1;
  try
  {
    if(extension == std::string(".tre"))
      {
      ReaderType::Pointer reader = ReaderType::New();
      reader->SetFileName(fullName);
      reader->Update();
      // WARNING : Should we check if the tube contains less than 2 points...

      char childName[] = "Tube";
      TubeNetType::ChildrenListType* tubeList =
        reader->GetGroup()->GetChildren(reader->GetGroup()->GetMaximumDepth(), childName);

      // -----------------------------------------------------------------------
      // Copy skeleton points from vessels into polydata structure
      // -----------------------------------------------------------------------

      // Initialize the SpatialObject
      // Count number of points && remove dupplicate
      int totalNumberOfPoints = 0;
      for(TubeNetType::ChildrenListType::iterator tubeIT = tubeList->begin();
           tubeIT != tubeList->end();
           ++tubeIT )
        {
        TubeType* currTube =
          static_cast<TubeType*>((*tubeIT).GetPointer());

        currTube->RemoveDuplicatePoints();

        if(currTube->GetNumberOfPoints() < 2)
          continue;

        totalNumberOfPoints += currTube->GetNumberOfPoints();
        }

      // Create the points
      vtkNew<vtkPoints> vesselsPoints;
      vesselsPoints->SetNumberOfPoints(totalNumberOfPoints);

      // Create the Lines
      vtkNew<vtkCellArray> vesselLinesCA;

      // Create scalar array that indicates the radius at each
      // centerline point.
      vtkNew<vtkDoubleArray> tubeRadius;
      tubeRadius->SetName("TubeRadius");
      tubeRadius->SetNumberOfTuples(totalNumberOfPoints);

      // Create scalar array that indicates TubeID.
      vtkNew<vtkDoubleArray> tubeIDs;
      tubeIDs->SetName("TubeIDs");
      tubeIDs->SetNumberOfTuples(totalNumberOfPoints);

      // Create scalar array that indicates both tangeantes at each
      // centerline point.
      vtkNew<vtkDoubleArray> tan1;
      tan1->SetName("Tan1");
      tan1->SetNumberOfTuples(3 * totalNumberOfPoints);
      tan1->SetNumberOfComponents(3);

      vtkNew<vtkDoubleArray> tan2;
      tan2->SetName("Tan2");
      tan2->SetNumberOfTuples(3 * totalNumberOfPoints);
      tan2->SetNumberOfComponents(3);

      // Create scalar array that indicates Ridgness and medialness at each
      // centerline point.
      bool containsMidialnessInfo = false;
      vtkNew<vtkDoubleArray> medialness;
      medialness->SetName("Medialness");
      medialness->SetNumberOfTuples(totalNumberOfPoints);

      bool containsRidgnessInfo = false;
      vtkNew<vtkDoubleArray> ridgeness;
      ridgeness->SetName("Ridgeness");
      ridgeness->SetNumberOfTuples(totalNumberOfPoints);

      int pointID = 0;
      for(TubeNetType::ChildrenListType::iterator tubeIT = tubeList->begin();
           tubeIT != tubeList->end(); ++tubeIT )
        {
        TubeType* currTube =
          static_cast<TubeType*>((*tubeIT).GetPointer());

        currTube->RemoveDuplicatePoints();

        int tubeSize = currTube->GetNumberOfPoints();
        if(tubeSize < 2)
          continue;

        currTube->ComputeTangentAndNormals();

        // Create a pointID list [linear for a polyline]
        vtkIdType* pointIDs = new vtkIdType[tubeSize];
        vtkNew<vtkPolyLine> vesselLine;

        // Get the tube element spacing information.
        const double* axesRatio = currTube->GetSpacing();

        int index = 0;
        std::vector<TubePointType>::iterator  tubePointIterator;
        for(tubePointIterator = currTube->GetPoints().begin();
             tubePointIterator != currTube->GetPoints().end();
             ++tubePointIterator, ++pointID, ++index)
          {
          PointType inputPoint = tubePointIterator->GetPosition();
          pointIDs[index] = pointID;

          // Insert points using the element spacing information.
          vesselsPoints->SetPoint(pointID,
                                  inputPoint[0],
                                  inputPoint[1] * axesRatio[1] / axesRatio[0],
                                  inputPoint[2] * axesRatio[2] / axesRatio[0]);

          // TubeID
          tubeIDs->SetTuple1(pointID, currTube->GetId());

          // Radius
          tubeRadius->SetTuple1(pointID, tubePointIterator->GetRadius());

          // Tangeantes
          tan1->SetTuple3(pointID,
                          (*tubePointIterator).GetNormal1()[0],
                          (*tubePointIterator).GetNormal1()[1],
                          (*tubePointIterator).GetNormal1()[2]);

          tan2->SetTuple3(pointID,
                          (*tubePointIterator).GetNormal2()[0],
                          (*tubePointIterator).GetNormal2()[1],
                          (*tubePointIterator).GetNormal2()[2]);

          // Medialness & Ridgness
          if(tubePointIterator->GetMedialness() != 0)
            {
            containsMidialnessInfo = true;
            }
          medialness->SetTuple1(pointID, tubePointIterator->GetMedialness());

          if(tubePointIterator->GetRidgeness() != 0)
            {
            containsRidgnessInfo = true;
            }
          ridgeness->SetTuple1(pointID, tubePointIterator->GetRidgeness());
          }

        vesselLine->Initialize(tubeSize,
                               pointIDs,
                               vesselsPoints.GetPointer());
        vesselLinesCA->InsertNextCell(vesselLine.GetPointer());
        delete [] pointIDs;
        }

      // Convert spatial objects to a PolyData
      vtkNew<vtkPolyData> vesselsPD;
      vesselsPD->SetLines(vesselLinesCA.GetPointer());
      vesselsPD->SetPoints(vesselsPoints.GetPointer());

      // Add the Radius information
      vesselsPD->GetPointData()->AddArray(tubeRadius.GetPointer());
      vesselsPD->GetPointData()->SetActiveScalars("TubeRadius");

      // Add the TudeID information
      vesselsPD->GetPointData()->AddArray(tubeIDs.GetPointer());

      // Add Tangeantes information
      vesselsPD->GetPointData()->AddArray(tan1.GetPointer());
      vesselsPD->GetPointData()->AddArray(tan2.GetPointer());

      // Add Medialness & Ridgness if contains information
      if(containsMidialnessInfo == true)
        {
        vesselsPD->GetPointData()->AddArray(medialness.GetPointer());
        }

      if(containsRidgnessInfo == true)
        {
        vesselsPD->GetPointData()->AddArray(ridgeness.GetPointer());
        }

      // Remove any duplicate points from polydata.
      // The tubes generation will fails if any duplicates points are present.
      // Cleaned before, could create degeneration problems with the cells
      //vtkNew<vtkCleanPolyData> cleanedVesselPD;
      //cleanedVesselPD->SetInput(vesselsPD.GetPointer());

      vtkDebugMacro("Points: " << totalNumberOfPoints);

      spatialObjectsNode->SetAndObservePolyData(vesselsPD.GetPointer());
      spatialObjectsNode->SetSpatialObject(reader->GetGroup());
      delete tubeList;
    }
  }
  catch(...)
  {
    result = 0;
  }

  if(spatialObjectsNode->GetPolyData() != NULL)
    {
    // is there an active scalar array?
    if(spatialObjectsNode->GetDisplayNode())
      {
      double *scalarRange = spatialObjectsNode->GetPolyData()->GetScalarRange();
      if(scalarRange)
        {
        vtkDebugMacro("ReadData: setting scalar range " << scalarRange[0]
                      << ", " << scalarRange[1]);
        spatialObjectsNode->GetDisplayNode()->SetScalarRange(scalarRange);
        }
      }

    spatialObjectsNode->GetPolyData()->Modified();
    }

  return result;
}

//------------------------------------------------------------------------------
int vtkMRMLSpatialObjectsStorageNode::WriteDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLSpatialObjectsNode* spatialObjects =
    vtkMRMLSpatialObjectsNode::SafeDownCast(refNode);

  std::string fullName = this->GetFullNameFromFileName();
  if(fullName == std::string(""))
    {
    vtkErrorMacro("vtkMRMLModelNode: File name not specified");
    return 0;
    }

  std::string extension =
    itksys::SystemTools::GetFilenameLastExtension(fullName);

  int result = 1;
  if(extension == ".tre")
    {
    try
      {
      WriterType::Pointer writer = WriterType::New();
      writer->SetFileName(fullName.c_str());
      writer->SetInput(spatialObjects->GetSpatialObject());
      writer->Update();
      }
    catch(...)
      {
      result = 0;
      vtkErrorMacro("Error occured writing Spatial Objects: "
                    << fullName.c_str());
      }
    }
  else
    {
    result = 0;
    vtkErrorMacro( << "No file extension recognized: " << fullName.c_str());
    }

  return result;
}

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::InitializeSupportedReadFileTypes( void )
{
  this->SupportedReadFileTypes->InsertNextValue("SpatialObject (.tre)");
}

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::InitializeSupportedWriteFileTypes( void )
{
  this->SupportedWriteFileTypes->InsertNextValue("SpatialObject (.tre)");
}

//------------------------------------------------------------------------------
const char* vtkMRMLSpatialObjectsStorageNode::GetDefaultWriteFileExtension( void )
{
  return "tre";
}
<commit_msg>STYLE: Const correctness and types in vtkMRMLSpatialObjectsStorageNode.cxx.<commit_after>/*=========================================================================

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

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 <vtkObjectFactory.h>

// MRML includes
#include "vtkMRMLSpatialObjectsStorageNode.h"
#include "vtkMRMLSpatialObjectsNode.h"
#include "vtkMRMLSpatialObjectsDisplayNode.h"

// VTK includes
#include <vtkAppendPolyData.h>
#include <vtkCellArray.h>
#include <vtkCleanPolyData.h>
#include <vtkDoubleArray.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyLine.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkStringArray.h>

// ITK includes
#include <itkTubeSpatialObject.h>
#include <itkSpatialObjectReader.h>
#include <itkSpatialObjectWriter.h>

//------------------------------------------------------------------------------
vtkMRMLNodeNewMacro(vtkMRMLSpatialObjectsStorageNode);

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

//------------------------------------------------------------------------------
bool vtkMRMLSpatialObjectsStorageNode::
CanReadInReferenceNode(vtkMRMLNode *refNode)
{
  return refNode->IsA("vtkMRMLSpatialObjectsNode");
}

//------------------------------------------------------------------------------
int vtkMRMLSpatialObjectsStorageNode::ReadDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLSpatialObjectsNode* spatialObjectsNode =
    vtkMRMLSpatialObjectsNode::SafeDownCast(refNode);

  if(Superclass::ReadDataInternal(refNode) != 0)
    {
    return 0;
    }

  std::string fullName = this->GetFullNameFromFileName();
  if(fullName == std::string(""))
    {
    vtkErrorMacro("ReadData: File name not specified");
    return 0;
    }

  // compute file prefix
  std::string name(fullName);
  std::string::size_type loc = name.find_last_of(".");
  if( loc == std::string::npos )
    {
    vtkErrorMacro("ReadData: no file extension specified: " << name.c_str());
    return 0;
    }
  std::string extension = name.substr(loc);
  vtkDebugMacro("ReadData: extension = " << extension.c_str());

  int result = 1;
  try
  {
    if(extension == std::string(".tre"))
      {
      ReaderType::Pointer reader = ReaderType::New();
      reader->SetFileName(fullName);
      reader->Update();
      // WARNING : Should we check if the tube contains less than 2 points...

      char childName[] = "Tube";
      TubeNetType::ChildrenListType* tubeList =
        reader->GetGroup()->GetChildren(reader->GetGroup()->GetMaximumDepth(), childName);

      // -----------------------------------------------------------------------
      // Copy skeleton points from vessels into polydata structure
      // -----------------------------------------------------------------------

      // Initialize the SpatialObject
      // Count number of points && remove dupplicate
      int totalNumberOfPoints = 0;
      for(TubeNetType::ChildrenListType::iterator tubeIT = tubeList->begin();
           tubeIT != tubeList->end();
           ++tubeIT )
        {
        TubeType* currTube =
          static_cast<TubeType*>((*tubeIT).GetPointer());

        currTube->RemoveDuplicatePoints();

        const itk::SizeValueType numberOfPoints = currTube->GetNumberOfPoints();
        if( numberOfPoints < 2 )
          {
          continue;
          }

        totalNumberOfPoints += numberOfPoints;
        }

      // Create the points
      vtkNew<vtkPoints> vesselsPoints;
      vesselsPoints->SetNumberOfPoints(totalNumberOfPoints);

      // Create the Lines
      vtkNew<vtkCellArray> vesselLinesCA;

      // Create scalar array that indicates the radius at each
      // centerline point.
      vtkNew<vtkDoubleArray> tubeRadius;
      tubeRadius->SetName("TubeRadius");
      tubeRadius->SetNumberOfTuples(totalNumberOfPoints);

      // Create scalar array that indicates TubeID.
      vtkNew<vtkDoubleArray> tubeIDs;
      tubeIDs->SetName("TubeIDs");
      tubeIDs->SetNumberOfTuples(totalNumberOfPoints);

      // Create scalar array that indicates both tangents at each
      // centerline point.
      vtkNew<vtkDoubleArray> tan1;
      tan1->SetName("Tan1");
      tan1->SetNumberOfTuples(3 * totalNumberOfPoints);
      tan1->SetNumberOfComponents(3);

      vtkNew<vtkDoubleArray> tan2;
      tan2->SetName("Tan2");
      tan2->SetNumberOfTuples(3 * totalNumberOfPoints);
      tan2->SetNumberOfComponents(3);

      // Create scalar array that indicates Ridgness and medialness at each
      // centerline point.
      bool containsMidialnessInfo = false;
      vtkNew<vtkDoubleArray> medialness;
      medialness->SetName("Medialness");
      medialness->SetNumberOfTuples(totalNumberOfPoints);

      bool containsRidgnessInfo = false;
      vtkNew<vtkDoubleArray> ridgeness;
      ridgeness->SetName("Ridgeness");
      ridgeness->SetNumberOfTuples(totalNumberOfPoints);

      int pointID = 0;
      for(TubeNetType::ChildrenListType::iterator tubeIT = tubeList->begin();
           tubeIT != tubeList->end(); ++tubeIT )
        {
        TubeType* currTube =
          static_cast<TubeType*>((*tubeIT).GetPointer());

        const itk::SizeValueType tubeSize = currTube->GetNumberOfPoints();
        if( tubeSize < 2 )
          {
          continue;
          }

        currTube->ComputeTangentAndNormals();

        // Create a pointID list [linear for a polyline]
        vtkIdType* pointIDs = new vtkIdType[tubeSize];
        vtkNew<vtkPolyLine> vesselLine;

        // Get the tube element spacing information.
        const double* axesRatio = currTube->GetSpacing();

        int index = 0;
        std::vector<TubePointType>::iterator  tubePointIterator;
        for(tubePointIterator = currTube->GetPoints().begin();
             tubePointIterator != currTube->GetPoints().end();
             ++tubePointIterator, ++pointID, ++index)
          {
          PointType inputPoint = tubePointIterator->GetPosition();
          pointIDs[index] = pointID;

          // Insert points using the element spacing information.
          vesselsPoints->SetPoint(pointID,
                                  inputPoint[0],
                                  inputPoint[1] * axesRatio[1] / axesRatio[0],
                                  inputPoint[2] * axesRatio[2] / axesRatio[0]);

          // TubeID
          tubeIDs->SetTuple1(pointID, currTube->GetId());

          // Radius
          tubeRadius->SetTuple1(pointID, tubePointIterator->GetRadius());

          // Tangeantes
          tan1->SetTuple3(pointID,
                          (*tubePointIterator).GetNormal1()[0],
                          (*tubePointIterator).GetNormal1()[1],
                          (*tubePointIterator).GetNormal1()[2]);

          tan2->SetTuple3(pointID,
                          (*tubePointIterator).GetNormal2()[0],
                          (*tubePointIterator).GetNormal2()[1],
                          (*tubePointIterator).GetNormal2()[2]);

          // Medialness & Ridgness
          if(tubePointIterator->GetMedialness() != 0)
            {
            containsMidialnessInfo = true;
            }
          medialness->SetTuple1(pointID, tubePointIterator->GetMedialness());

          if(tubePointIterator->GetRidgeness() != 0)
            {
            containsRidgnessInfo = true;
            }
          ridgeness->SetTuple1(pointID, tubePointIterator->GetRidgeness());
          }

        vesselLine->Initialize(tubeSize,
                               pointIDs,
                               vesselsPoints.GetPointer());
        vesselLinesCA->InsertNextCell(vesselLine.GetPointer());
        delete [] pointIDs;
        }

      // Convert spatial objects to a PolyData
      vtkNew<vtkPolyData> vesselsPD;
      vesselsPD->SetLines(vesselLinesCA.GetPointer());
      vesselsPD->SetPoints(vesselsPoints.GetPointer());

      // Add the Radius information
      vesselsPD->GetPointData()->AddArray(tubeRadius.GetPointer());
      vesselsPD->GetPointData()->SetActiveScalars("TubeRadius");

      // Add the TudeID information
      vesselsPD->GetPointData()->AddArray(tubeIDs.GetPointer());

      // Add Tangeantes information
      vesselsPD->GetPointData()->AddArray(tan1.GetPointer());
      vesselsPD->GetPointData()->AddArray(tan2.GetPointer());

      // Add Medialness & Ridgness if contains information
      if(containsMidialnessInfo == true)
        {
        vesselsPD->GetPointData()->AddArray(medialness.GetPointer());
        }

      if(containsRidgnessInfo == true)
        {
        vesselsPD->GetPointData()->AddArray(ridgeness.GetPointer());
        }

      // Remove any duplicate points from polydata.
      // The tubes generation will fails if any duplicates points are present.
      // Cleaned before, could create degeneration problems with the cells
      //vtkNew<vtkCleanPolyData> cleanedVesselPD;
      //cleanedVesselPD->SetInput(vesselsPD.GetPointer());

      vtkDebugMacro("Points: " << totalNumberOfPoints);

      spatialObjectsNode->SetAndObservePolyData(vesselsPD.GetPointer());
      spatialObjectsNode->SetSpatialObject(reader->GetGroup());
      delete tubeList;
    }
  }
  catch(...)
  {
    result = 0;
  }

  if(spatialObjectsNode->GetPolyData() != NULL)
    {
    // is there an active scalar array?
    if(spatialObjectsNode->GetDisplayNode())
      {
      double *scalarRange = spatialObjectsNode->GetPolyData()->GetScalarRange();
      if(scalarRange)
        {
        vtkDebugMacro("ReadData: setting scalar range " << scalarRange[0]
                      << ", " << scalarRange[1]);
        spatialObjectsNode->GetDisplayNode()->SetScalarRange(scalarRange);
        }
      }

    spatialObjectsNode->GetPolyData()->Modified();
    }

  return result;
}

//------------------------------------------------------------------------------
int vtkMRMLSpatialObjectsStorageNode::WriteDataInternal(vtkMRMLNode *refNode)
{
  vtkMRMLSpatialObjectsNode* spatialObjects =
    vtkMRMLSpatialObjectsNode::SafeDownCast(refNode);

  const std::string fullName = this->GetFullNameFromFileName();
  if(fullName == std::string(""))
    {
    vtkErrorMacro("vtkMRMLModelNode: File name not specified");
    return 0;
    }

  const std::string extension =
    itksys::SystemTools::GetFilenameLastExtension(fullName);

  int result = 1;
  if(extension == ".tre")
    {
    try
      {
      WriterType::Pointer writer = WriterType::New();
      writer->SetFileName(fullName.c_str());
      writer->SetInput(spatialObjects->GetSpatialObject());
      writer->Update();
      }
    catch(...)
      {
      result = 0;
      vtkErrorMacro("Error occured writing Spatial Objects: "
                    << fullName.c_str());
      }
    }
  else
    {
    result = 0;
    vtkErrorMacro( << "No file extension recognized: " << fullName.c_str());
    }

  return result;
}

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::InitializeSupportedReadFileTypes( void )
{
  this->SupportedReadFileTypes->InsertNextValue("SpatialObject (.tre)");
}

//------------------------------------------------------------------------------
void vtkMRMLSpatialObjectsStorageNode::InitializeSupportedWriteFileTypes( void )
{
  this->SupportedWriteFileTypes->InsertNextValue("SpatialObject (.tre)");
}

//------------------------------------------------------------------------------
const char* vtkMRMLSpatialObjectsStorageNode::GetDefaultWriteFileExtension( void )
{
  return "tre";
}
<|endoftext|>


<commit_before>#include "libnanocv/minimize.h"
#include "libnanocv/tabulator.h"
#include "libnanocv/math/abs.hpp"
#include "libnanocv/util/timer.h"
#include "libnanocv/math/math.hpp"
#include "libnanocv/util/logger.h"
#include "libnanocv/util/stats.hpp"
#include "libnanocv/math/clamp.hpp"
#include "libnanocv/util/random.hpp"
#include "libnanocv/math/epsilon.hpp"
#include "libnanocv/thread/parallel.hpp"

#include "libnanocv/functions/function_trid.h"
#include "libnanocv/functions/function_beale.h"
#include "libnanocv/functions/function_booth.h"
#include "libnanocv/functions/function_sphere.h"
#include "libnanocv/functions/function_matyas.h"
#include "libnanocv/functions/function_powell.h"
#include "libnanocv/functions/function_mccormick.h"
#include "libnanocv/functions/function_himmelblau.h"
#include "libnanocv/functions/function_rosenbrock.h"
#include "libnanocv/functions/function_3hump_camel.h"
#include "libnanocv/functions/function_sum_squares.h"
#include "libnanocv/functions/function_dixon_price.h"
#include "libnanocv/functions/function_goldstein_price.h"
#include "libnanocv/functions/function_rotated_ellipsoid.h"

#include <map>
#include <tuple>

using namespace ncv;

const size_t trials = 1024;

struct optimizer_stat_t
{
        stats_t<scalar_t>       m_time;
        stats_t<scalar_t>       m_crits;
        stats_t<scalar_t>       m_fails;
        stats_t<scalar_t>       m_iters;
        stats_t<scalar_t>       m_fvals;
        stats_t<scalar_t>       m_grads;
};

std::map<string_t, optimizer_stat_t> optimizer_stats;

static void check_problem(
        const string_t& problem_name,
        const opt_opsize_t& fn_size, const opt_opfval_t& fn_fval, const opt_opgrad_t& fn_grad,
        const std::vector<std::pair<vector_t, scalar_t>>&)
{
        const size_t iterations = 1024;
        const scalar_t epsilon = 1e-6;

        const size_t dims = fn_size();

        // generate fixed random trials
        vectors_t x0s;
        for (size_t t = 0; t < trials; t ++)
        {
                random_t<scalar_t> rgen(-1.0, +1.0);

                vector_t x0(dims);
                rgen(x0.data(), x0.data() + x0.size());

                x0s.push_back(x0);
        }

        // optimizers to try
        const auto optimizers =
        {
//                batch_optimizer::GD,
//                batch_optimizer::CGD_CD,
//                batch_optimizer::CGD_DY,
//                batch_optimizer::CGD_FR,
//                batch_optimizer::CGD_HS,
//                batch_optimizer::CGD_LS,
                batch_optimizer::CGD_PRP,
                batch_optimizer::CGD_N,
                batch_optimizer::CGD_DYCD,
                batch_optimizer::CGD_DYHS,
                batch_optimizer::LBFGS
        };

        const auto ls_initializers =
        {
                optimize::ls_initializer::unit,
                optimize::ls_initializer::quadratic,
                optimize::ls_initializer::consistent
        };

        const auto ls_strategies =
        {
//                optimize::ls_strategy::backtrack_armijo,
//                optimize::ls_strategy::backtrack_wolfe,
//                optimize::ls_strategy::backtrack_strong_wolfe,
//                optimize::ls_strategy::interpolation_bisection,
//                optimize::ls_strategy::interpolation_cubic,
                optimize::ls_strategy::cg_descent
        };

        tabulator_t table(text::resize(problem_name, 32));
        table.header() << "cost"
                       << "time [us]"
                       << "|grad|/|fval|"
                       << "#fails"
                       << "#iters"
                       << "#fvals"
                       << "#grads";

        thread_pool_t pool;
        thread_pool_t::mutex_t mutex;

        for (batch_optimizer optimizer : optimizers)
                for (optimize::ls_initializer ls_initializer : ls_initializers)
                        for (optimize::ls_strategy ls_strategy : ls_strategies)
        {
                stats_t<scalar_t> times;
                stats_t<scalar_t> crits;
                stats_t<scalar_t> fails;
                stats_t<scalar_t> iters;
                stats_t<scalar_t> fvals;
                stats_t<scalar_t> grads;

                thread_loopi(trials, pool, [&] (size_t t)
                {
                        const vector_t& x0 = x0s[t];

                        // check gradients
                        const opt_problem_t problem(fn_size, fn_fval, fn_grad);
                        if (problem.grad_accuracy(x0) > math::epsilon2<scalar_t>())
                        {
                                const thread_pool_t::lock_t lock(mutex);

                                log_error() << "invalid gradient for problem [" << problem_name << "]!";
                        }

                        // optimize
                        const ncv::timer_t timer;

                        const opt_state_t state = ncv::minimize(
                                fn_size, fn_fval, fn_grad, nullptr, nullptr, nullptr,
                                x0, optimizer, iterations, epsilon, ls_initializer, ls_strategy);

                        const scalar_t crit = state.convergence_criteria();

                        // update stats
                        const thread_pool_t::lock_t lock(mutex);

                        times(timer.microseconds());
                        crits(crit);
                        iters(state.n_iterations());
                        fvals(state.n_fval_calls());
                        grads(state.n_grad_calls());

                        fails(!state.converged(epsilon) ? 1.0 : 0.0);
                });

                // update per-problem table
                const string_t name =
                        text::to_string(optimizer) + "[" +
                        text::to_string(ls_initializer) + "][" +
                        text::to_string(ls_strategy) + "]";

                table.append(name)
                        << static_cast<int>(fvals.sum() + 2 * grads.sum()) / trials
                        << times.avg()
                        << crits.avg()
                        << static_cast<int>(fails.sum())
                        << iters.avg()
                        << fvals.avg()
                        << grads.avg();

                // update global statistics
                optimizer_stat_t& stat = optimizer_stats[name];
                stat.m_time(times.avg());
                stat.m_crits(crits.avg());
                stat.m_fails(fails.sum());
                stat.m_iters(iters.avg());
                stat.m_fvals(fvals.avg());
                stat.m_grads(grads.avg());
        }

        // print stats
        table.sort_as_number_ascending(3);
        table.print(std::cout);
}

static void check_problems(const std::vector<ncv::function_t>& funcs)
{
        for (const ncv::function_t& func : funcs)
        {
                check_problem(func.m_name, func.m_opsize, func.m_opfval, func.m_opgrad, func.m_solutions);
        }
}

int main(int argc, char *argv[])
{
        using namespace ncv;

        check_problems(ncv::make_beale_funcs());
        check_problems(ncv::make_booth_funcs());
        check_problems(ncv::make_matyas_funcs());
        check_problems(ncv::make_trid_funcs(128));
        check_problems(ncv::make_sphere_funcs(128));
        check_problems(ncv::make_powell_funcs(128));
        check_problems(ncv::make_mccormick_funcs());
        check_problems(ncv::make_himmelblau_funcs());
        check_problems(ncv::make_rosenbrock_funcs(7));
        check_problems(ncv::make_3hump_camel_funcs());
        check_problems(ncv::make_dixon_price_funcs(128));
        check_problems(ncv::make_sum_squares_funcs(128));
        check_problems(ncv::make_goldstein_price_funcs());
        check_problems(ncv::make_rotated_ellipsoid_funcs(128));

        // show global statistics
        tabulator_t table(text::resize("optimizer", 32));
        table.header() << "cost"
                       << "time [us]"
                       << "|grad|/|fval|"
                       << "#fails"
                       << "#iters"
                       << "#fvals"
                       << "#grads";

        for (const auto& it : optimizer_stats)
        {
                const string_t& name = it.first;
                const optimizer_stat_t& stat = it.second;

                table.append(name) << static_cast<int>(stat.m_fvals.sum() + 2 * stat.m_grads.sum())
                                   << stat.m_time.sum()
                                   << stat.m_crits.avg()
                                   << static_cast<int>(stat.m_fails.sum())
                                   << stat.m_iters.sum()
                                   << stat.m_fvals.sum()
                                   << stat.m_grads.sum();
        }

        table.sort_as_number_ascending(3);
        table.print(std::cout);

        // OK
        log_info() << done;
        return EXIT_SUCCESS;
}

<commit_msg>update unit test<commit_after>#include "libnanocv/minimize.h"
#include "libnanocv/tabulator.h"
#include "libnanocv/math/abs.hpp"
#include "libnanocv/util/timer.h"
#include "libnanocv/math/math.hpp"
#include "libnanocv/util/logger.h"
#include "libnanocv/util/stats.hpp"
#include "libnanocv/math/clamp.hpp"
#include "libnanocv/util/random.hpp"
#include "libnanocv/math/epsilon.hpp"
#include "libnanocv/thread/parallel.hpp"

#include "libnanocv/functions/function_trid.h"
#include "libnanocv/functions/function_beale.h"
#include "libnanocv/functions/function_booth.h"
#include "libnanocv/functions/function_sphere.h"
#include "libnanocv/functions/function_matyas.h"
#include "libnanocv/functions/function_powell.h"
#include "libnanocv/functions/function_mccormick.h"
#include "libnanocv/functions/function_himmelblau.h"
#include "libnanocv/functions/function_rosenbrock.h"
#include "libnanocv/functions/function_3hump_camel.h"
#include "libnanocv/functions/function_sum_squares.h"
#include "libnanocv/functions/function_dixon_price.h"
#include "libnanocv/functions/function_goldstein_price.h"
#include "libnanocv/functions/function_rotated_ellipsoid.h"

#include <map>
#include <tuple>

using namespace ncv;

const size_t trials = 1024;

struct optimizer_stat_t
{
        stats_t<scalar_t>       m_time;
        stats_t<scalar_t>       m_crits;
        stats_t<scalar_t>       m_fails;
        stats_t<scalar_t>       m_iters;
        stats_t<scalar_t>       m_fvals;
        stats_t<scalar_t>       m_grads;
};

std::map<string_t, optimizer_stat_t> optimizer_stats;

static void check_problem(
        const string_t& problem_name,
        const opt_opsize_t& fn_size, const opt_opfval_t& fn_fval, const opt_opgrad_t& fn_grad,
        const std::vector<std::pair<vector_t, scalar_t>>&)
{
        const size_t iterations = 1024;
        const scalar_t epsilon = 1e-6;

        const size_t dims = fn_size();

        // generate fixed random trials
        vectors_t x0s;
        for (size_t t = 0; t < trials; t ++)
        {
                random_t<scalar_t> rgen(-1.0, +1.0);

                vector_t x0(dims);
                rgen(x0.data(), x0.data() + x0.size());

                x0s.push_back(x0);
        }

        // optimizers to try
        const auto optimizers =
        {
//                batch_optimizer::GD,
//                batch_optimizer::CGD_CD,
//                batch_optimizer::CGD_DY,
//                batch_optimizer::CGD_FR,
//                batch_optimizer::CGD_HS,
//                batch_optimizer::CGD_LS,
                batch_optimizer::CGD_PRP,
                batch_optimizer::CGD_N,
                batch_optimizer::CGD_DYCD,
                batch_optimizer::CGD_DYHS,
                batch_optimizer::LBFGS
        };

        const auto ls_initializers =
        {
                optimize::ls_initializer::unit,
                optimize::ls_initializer::quadratic,
                optimize::ls_initializer::consistent
        };

        const auto ls_strategies =
        {
//                optimize::ls_strategy::backtrack_armijo,
//                optimize::ls_strategy::backtrack_wolfe,
//                optimize::ls_strategy::backtrack_strong_wolfe,
//                optimize::ls_strategy::interpolation_bisection,
                optimize::ls_strategy::interpolation_cubic,
                optimize::ls_strategy::cg_descent
        };

        tabulator_t table(text::resize(problem_name, 32));
        table.header() << "cost"
                       << "time [us]"
                       << "|grad|/|fval|"
                       << "#fails"
                       << "#iters"
                       << "#fvals"
                       << "#grads";

        thread_pool_t pool;
        thread_pool_t::mutex_t mutex;

        for (batch_optimizer optimizer : optimizers)
                for (optimize::ls_initializer ls_initializer : ls_initializers)
                        for (optimize::ls_strategy ls_strategy : ls_strategies)
        {
                stats_t<scalar_t> times;
                stats_t<scalar_t> crits;
                stats_t<scalar_t> fails;
                stats_t<scalar_t> iters;
                stats_t<scalar_t> fvals;
                stats_t<scalar_t> grads;

                thread_loopi(trials, pool, [&] (size_t t)
                {
                        const vector_t& x0 = x0s[t];

                        // check gradients
                        const opt_problem_t problem(fn_size, fn_fval, fn_grad);
                        if (problem.grad_accuracy(x0) > math::epsilon2<scalar_t>())
                        {
                                const thread_pool_t::lock_t lock(mutex);

                                log_error() << "invalid gradient for problem [" << problem_name << "]!";
                        }

                        // optimize
                        const ncv::timer_t timer;

                        const opt_state_t state = ncv::minimize(
                                fn_size, fn_fval, fn_grad, nullptr, nullptr, nullptr,
                                x0, optimizer, iterations, epsilon, ls_initializer, ls_strategy);

                        const scalar_t crit = state.convergence_criteria();

                        // update stats
                        const thread_pool_t::lock_t lock(mutex);

                        times(timer.microseconds());
                        crits(crit);
                        iters(state.n_iterations());
                        fvals(state.n_fval_calls());
                        grads(state.n_grad_calls());

                        fails(!state.converged(epsilon) ? 1.0 : 0.0);
                });

                // update per-problem table
                const string_t name =
                        text::to_string(optimizer) + "[" +
                        text::to_string(ls_initializer) + "][" +
                        text::to_string(ls_strategy) + "]";

                table.append(name)
                        << static_cast<int>(fvals.sum() + 2 * grads.sum()) / trials
                        << times.avg()
                        << crits.avg()
                        << static_cast<int>(fails.sum())
                        << iters.avg()
                        << fvals.avg()
                        << grads.avg();

                // update global statistics
                optimizer_stat_t& stat = optimizer_stats[name];
                stat.m_time(times.avg());
                stat.m_crits(crits.avg());
                stat.m_fails(fails.sum());
                stat.m_iters(iters.avg());
                stat.m_fvals(fvals.avg());
                stat.m_grads(grads.avg());
        }

        // print stats
        table.sort_as_number_ascending(3);
        table.print(std::cout);
}

static void check_problems(const std::vector<ncv::function_t>& funcs)
{
        for (const ncv::function_t& func : funcs)
        {
                check_problem(func.m_name, func.m_opsize, func.m_opfval, func.m_opgrad, func.m_solutions);
        }
}

int main(int argc, char *argv[])
{
        using namespace ncv;

//        check_problems(ncv::make_beale_funcs());
        check_problems(ncv::make_booth_funcs());
        check_problems(ncv::make_matyas_funcs());
        check_problems(ncv::make_trid_funcs(128));
        check_problems(ncv::make_sphere_funcs(128));
        check_problems(ncv::make_powell_funcs(128));
        check_problems(ncv::make_mccormick_funcs());
        check_problems(ncv::make_himmelblau_funcs());
        check_problems(ncv::make_rosenbrock_funcs(7));
        check_problems(ncv::make_3hump_camel_funcs());
        check_problems(ncv::make_dixon_price_funcs(128));
        check_problems(ncv::make_sum_squares_funcs(128));
//        check_problems(ncv::make_goldstein_price_funcs());
        check_problems(ncv::make_rotated_ellipsoid_funcs(128));

        // show global statistics
        tabulator_t table(text::resize("optimizer", 32));
        table.header() << "cost"
                       << "time [us]"
                       << "|grad|/|fval|"
                       << "#fails"
                       << "#iters"
                       << "#fvals"
                       << "#grads";

        for (const auto& it : optimizer_stats)
        {
                const string_t& name = it.first;
                const optimizer_stat_t& stat = it.second;

                table.append(name) << static_cast<int>(stat.m_fvals.sum() + 2 * stat.m_grads.sum())
                                   << stat.m_time.sum()
                                   << stat.m_crits.avg()
                                   << static_cast<int>(stat.m_fails.sum())
                                   << stat.m_iters.sum()
                                   << stat.m_fvals.sum()
                                   << stat.m_grads.sum();
        }

        table.sort_as_number_ascending(3);
        table.print(std::cout);

        // OK
        log_info() << done;
        return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>void MakeADQAParamEntry(const char *outputCDB = "local://$ALICE_ROOT/OCDB") {
//========================================================================
//
// Steering macro for AD reconstruction parameters
//
// Author: Michal Broz
//
//========================================================================

  const char* macroname = "MakeADQAParamEntry.C";

  // Activate CDB storage and load geometry from CDB
  AliCDBManager* cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage(outputCDB);
  cdb->SetRun(0);

  AliADQAParam * ADQAParam = new AliADQAParam();
  ADQAParam->SetMaxPedDiff(1);
  ADQAParam->SetMaxPedWidth(1.5);
  ADQAParam->SetSatMed(0.1);
  ADQAParam->SetSatHigh(0.3);
  ADQAParam->SetSatHuge(0.7);

  ADQAParam->SetAsynchronBB(0.5);
  ADQAParam->SetAsynchronBG(1.0);

  ADQAParam->SetMaxBBVariation(0.2);
  ADQAParam->SetMaxBGVariation(0.2);

  ADQAParam->SetChargeChannelZoomMin(0);
  ADQAParam->SetChargeChannelZoomMax(50);

  ADQAParam->SetNTdcTimeBins(3062);
  ADQAParam->SetTdcTimeMin(0.976562);
  ADQAParam->SetTdcTimeMax(300.0);

  ADQAParam->SetNChargeChannelBins(7000);
  ADQAParam->SetChargeChannelMin(0);
  ADQAParam->SetChargeChannelMax(7000);

  ADQAParam->SetNChargeSideBins(5000);
  ADQAParam->SetChargeSideMin(10);
  ADQAParam->SetChargeSideMax(50000);

  // save in CDB storage
  AliCDBMetaData *md= new AliCDBMetaData();
  md->SetResponsible("Michal Broz");
  md->SetComment("Reconstruction parameters for AD");
  //md->SetAliRootVersion(gSystem->Getenv("ARVERSION"));
  //md->SetBeamPeriod(0);
  AliCDBId id("AD/Calib/QAParam", 0, AliCDBRunRange::Infinity());
  cdb->Put(ADQAParam, id, md);

  return;
}
<commit_msg>Updated QA params<commit_after>void MakeADQAParamEntry(const char *outputCDB = "local://$ALICE_ROOT/OCDB") {
//========================================================================
//
// Steering macro for AD reconstruction parameters
//
// Author: Michal Broz
//
//========================================================================

  const char* macroname = "MakeADQAParamEntry.C";

  // Activate CDB storage and load geometry from CDB
  AliCDBManager* cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage(outputCDB);
  cdb->SetRun(0);

  AliADQAParam * ADQAParam = new AliADQAParam();
  ADQAParam->SetMaxPedDiff(5);
  ADQAParam->SetMaxPedWidth(1.5);
  ADQAParam->SetSatMed(0.7);
  ADQAParam->SetSatHigh(0.9);
  ADQAParam->SetSatHuge(0.99);

  ADQAParam->SetAsynchronBB(5.0);
  ADQAParam->SetAsynchronBG(10.0);

  ADQAParam->SetMaxBBVariation(0.2);
  ADQAParam->SetMaxBGVariation(0.2);

  ADQAParam->SetMaxNoFlagRate(0.2);

  ADQAParam->SetChargeChannelZoomMin(0);
  ADQAParam->SetChargeChannelZoomMax(50);

  ADQAParam->SetNTdcTimeBins(3062);
  ADQAParam->SetTdcTimeMin(0.976562);
  ADQAParam->SetTdcTimeMax(300.0);

  ADQAParam->SetNChargeChannelBins(10000);
  ADQAParam->SetChargeChannelMin(0);
  ADQAParam->SetChargeChannelMax(10000);

  ADQAParam->SetNChargeSideBins(7000);
  ADQAParam->SetChargeSideMin(10);
  ADQAParam->SetChargeSideMax(70000);

  // save in CDB storage
  AliCDBMetaData *md= new AliCDBMetaData();
  md->SetResponsible("Michal Broz");
  md->SetComment("Reconstruction parameters for AD");
  //md->SetAliRootVersion(gSystem->Getenv("ARVERSION"));
  //md->SetBeamPeriod(0);
  AliCDBId id("AD/Calib/QAParam", 0, AliCDBRunRange::Infinity());
  cdb->Put(ADQAParam, id, md);

  return;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "PvpPotion.h"
#include "../../Common/ETypes.h"
#include "../../Common/Helpers/RapidHelper.hpp"

#include <ATF/global.hpp>

namespace GameServer
{
    namespace Addon
    {
        #define CheckEffLimType(x, y) \
            (x == y && x != -1 && y != -1)

        bool CPvpPotion::m_bActivated = false;
        CPvpPotion::TempEffectFunc_Cont CPvpPotion::g_TempEffectFunc;

        void CPvpPotion::load()
        {
            TempEffectFunc_Ptr* origTempEffectFunc = (TempEffectFunc_Ptr*)0x14096CDF0L;
            for (int i = 0; i < detail::count_orig_effect_func; ++i)
            {
                g_TempEffectFunc[i] = origTempEffectFunc[i];
            }

            ::std::vector<::std::pair<int, TempEffectFunc_Ptr>> vecNewFunc{
                { 182, &AlterMoneyPotion<e_money_type::cp> },
                { 183, &AlterMoneyPotion<e_money_type::gold> },
                { 184, &AlterMoneyPotion<e_money_type::pvp_point> },
                { 185, &AlterMoneyPotion<e_money_type::pvp_point_2> },
                { 186, &AlterMoneyPotion<e_money_type::processing_point> },
                { 187, &AlterMoneyPotion<e_money_type::hunter_point> },
                { 188, &AlterMoneyPotion<e_money_type::gold_point> }
            };

            for (auto& kv : vecNewFunc)
            {
                g_TempEffectFunc[kv.first] = kv.second;
            }

            enable_hook(&ATF::CPotionMgr::ApplyPotion, &CPvpPotion::ApplyPotion);
        }

        void CPvpPotion::unload()
        {
            cleanup_all_hook();
        }

        Yorozuya::Module::ModuleName_t CPvpPotion::get_name()
        {
            static const Yorozuya::Module::ModuleName_t name = "addons.pvp_potion";
            return name;
        }

        void CPvpPotion::configure(const rapidjson::Value & nodeConfig)
        {
            CPvpPotion::m_bActivated = RapidHelper::GetValueOrDefault(nodeConfig, "activated", false);
        }

        int CPvpPotion::ApplyPotion(
            ATF::CPotionMgr* pObj,
            ATF::CPlayer* pUsePlayer,
            ATF::CPlayer* pApplyPlayer,
            ATF::_skill_fld* pEffecFld,
            ATF::_CheckPotion_fld* pCheckFld,
            ATF::_PotionItem_fld* pfB,
            bool bCommonPotion,
            ATF::Info::CPotionMgrApplyPotion2_ptr next)
        {
            if (!CPvpPotion::m_bActivated)
                return next(pObj, pUsePlayer, pApplyPlayer, pEffecFld, pCheckFld, pfB, bCommonPotion);

            if (!pUsePlayer || !pApplyPlayer || !pEffecFld)
                return -1;

            if (pCheckFld)
            {
                for (auto& i : pCheckFld->m_CheckEffectCode)
                {
                    if (!ATF::Global::_CheckPotionData(&i, pApplyPlayer))
                        return 19;
                }
            }

            int nContEffectResult = -1;
            int nResult = -1;

            if (pEffecFld->m_nContEffectType != -1 && bCommonPotion)
            {
                int indxDelBuff = 0;
                bool bExpiresBuff = false;
                for (int k = 0; k < _countof(pUsePlayer->m_PotionParam.m_ContCommonPotionData); ++k)
                {
                    int n = pUsePlayer->m_PotionParam.m_ContCommonPotionData[k].GetEffectIndex();
                    auto pPotionFld = (ATF::_PotionItem_fld*)ATF::Global::g_MainThread
                        ->m_tblItemData[(int)e_code_item_table::tbl_code_potion].GetRecord(n);
                    auto pCurrFld = (ATF::_skill_fld*)pObj->m_tblPotionEffectData.GetRecord(n);

                    if (!pCurrFld)
                        continue;

                    if (CheckEffLimType(pCurrFld->m_nEffLimType, pEffecFld->m_nEffLimType) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType, pEffecFld->m_nEffLimType2) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType2, pEffecFld->m_nEffLimType) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType2, pEffecFld->m_nEffLimType2))
                    {
                        if (pPotionFld)
                        {
                            if (pPotionFld->m_nPotionCheck <= pfB->m_nPotionCheck)
                            {
                                bExpiresBuff = true;
                                indxDelBuff = k;
                            }
                        }
                    }
                }

                if (pApplyPlayer->m_PotionBufUse.IsExtPotionUse())
                {
                    if (!bExpiresBuff)
                        indxDelBuff = pObj->SelectDeleteBuf(pApplyPlayer, true, false);
                }
                else
                {
                    indxDelBuff = pObj->SelectDeleteBuf(pApplyPlayer, false, false);
                }

                if (indxDelBuff > _countof(pUsePlayer->m_PotionParam.m_ContCommonPotionData))
                    return 25;

                nContEffectResult = pObj->InsertPotionContEffect(
                    pApplyPlayer,
                    &pUsePlayer->m_PotionParam.m_ContCommonPotionData[indxDelBuff],
                    pEffecFld,
                    pEffecFld->m_nContEffectSec[0]);
            }

            if (pEffecFld->m_nTempEffectType != -1)
            {
                if (pEffecFld->m_nTempEffectType >= 150 &&
                    pEffecFld->m_nTempEffectType < 182)
                {
                    nResult = -1;
                }
                else
                {
                    float fValue = 0.0;
                    if (ATF::Global::_GetTempEffectValue(pEffecFld, pEffecFld->m_nTempEffectType, &fValue))
                    {
                        char nRet = -1;
                        auto fnEffect = CPvpPotion::g_TempEffectFunc[pEffecFld->m_nTempEffectType];
                        if (fnEffect && fnEffect(pUsePlayer, pApplyPlayer, fValue, &nRet))
                            nResult = 0;
                        else
                            nResult = nRet;
                    }
                    else
                    {
                        nResult = -1;
                    }
                }
            }

            int result;
            if (nContEffectResult && nResult)
                result = nContEffectResult;
            else
                result = 0;
            return result;
        }
    }
}
<commit_msg>Updated addon with pvp potion<commit_after>#include "stdafx.h"

#include "PvpPotion.h"
#include "../../Common/ETypes.h"
#include "../../Common/Helpers/RapidHelper.hpp"

#include <ATF/global.hpp>

namespace GameServer
{
    namespace Addon
    {
        #define CheckEffLimType(x, y) \
            (x == y && x != -1 && y != -1)

        bool CPvpPotion::m_bActivated = false;
        CPvpPotion::TempEffectFunc_Cont CPvpPotion::g_TempEffectFunc;

        void CPvpPotion::load()
        {
            TempEffectFunc_Ptr* origTempEffectFunc = (TempEffectFunc_Ptr*)0x14096CDF0L;
            for (int i = 0; i < detail::count_orig_effect_func; ++i)
            {
                g_TempEffectFunc[i] = origTempEffectFunc[i];
            }

            ::std::vector<::std::pair<int, TempEffectFunc_Ptr>> vecNewFunc{
                { 182, &AlterMoneyPotion<e_money_type::cp> },
                { 183, &AlterMoneyPotion<e_money_type::gold> },
                { 184, &AlterMoneyPotion<e_money_type::pvp_point> },
                { 185, &AlterMoneyPotion<e_money_type::pvp_point_2> },
                { 186, &AlterMoneyPotion<e_money_type::processing_point> },
                { 187, &AlterMoneyPotion<e_money_type::hunter_point> },
                { 188, &AlterMoneyPotion<e_money_type::gold_point> }
            };

            for (auto& kv : vecNewFunc)
            {
                g_TempEffectFunc[kv.first] = kv.second;
            }

            enable_hook(&ATF::CPotionMgr::ApplyPotion, &CPvpPotion::ApplyPotion);
        }

        void CPvpPotion::unload()
        {
            cleanup_all_hook();
        }

        Yorozuya::Module::ModuleName_t CPvpPotion::get_name()
        {
            static const Yorozuya::Module::ModuleName_t name = "addons.pvp_potion";
            return name;
        }

        void CPvpPotion::configure(const rapidjson::Value & nodeConfig)
        {
            CPvpPotion::m_bActivated = RapidHelper::GetValueOrDefault(nodeConfig, "activated", false);
        }

        int CPvpPotion::ApplyPotion(
            ATF::CPotionMgr* pObj,
            ATF::CPlayer* pUsePlayer,
            ATF::CPlayer* pApplyPlayer,
            ATF::_skill_fld* pEffecFld,
            ATF::_CheckPotion_fld* pCheckFld,
            ATF::_PotionItem_fld* pfB,
            bool bCommonPotion,
            ATF::Info::CPotionMgrApplyPotion2_ptr next)
        {
            if (!CPvpPotion::m_bActivated)
                return next(pObj, pUsePlayer, pApplyPlayer, pEffecFld, pCheckFld, pfB, bCommonPotion);

            if (!pUsePlayer || !pApplyPlayer || !pEffecFld)
                return -1;

            if (pCheckFld)
            {
                for (auto& i : pCheckFld->m_CheckEffectCode)
                {
                    if (!ATF::Global::_CheckPotionData(&i, pApplyPlayer))
                        return 19;
                }
            }

            int nContEffectResult = -1;
            int nResult = -1;

            if (pEffecFld->m_nContEffectType != -1 && bCommonPotion)
            {
                int indxDelBuff = 0;
                bool bExpiresBuff = false;
                for (int k = 0; k < _countof(pUsePlayer->m_PotionParam.m_ContCommonPotionData); ++k)
                {
                    int n = pUsePlayer->m_PotionParam.m_ContCommonPotionData[k].GetEffectIndex();
                    auto pPotionFld = (ATF::_PotionItem_fld*)ATF::Global::g_MainThread
                        ->m_tblItemData[(int)e_code_item_table::tbl_code_potion].GetRecord(n);
                    auto pCurrFld = (ATF::_skill_fld*)pObj->m_tblPotionEffectData.GetRecord(n);

                    if (!pCurrFld)
                        continue;

                    if (CheckEffLimType(pCurrFld->m_nEffLimType, pEffecFld->m_nEffLimType) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType, pEffecFld->m_nEffLimType2) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType2, pEffecFld->m_nEffLimType) ||
                        CheckEffLimType(pCurrFld->m_nEffLimType2, pEffecFld->m_nEffLimType2))
                    {
                        if (pPotionFld)
                        {
                            if (pPotionFld->m_nPotionCheck <= pfB->m_nPotionCheck)
                            {
                                bExpiresBuff = true;
                                indxDelBuff = k;
                            }
                        }
                    }
                }

                if (pApplyPlayer->m_PotionBufUse.IsExtPotionUse())
                {
                    if (!bExpiresBuff)
                        indxDelBuff = pObj->SelectDeleteBuf(pApplyPlayer, true, false);
                }
                else
                {
                    indxDelBuff = pObj->SelectDeleteBuf(pApplyPlayer, false, false);
                }

                if (indxDelBuff > _countof(pUsePlayer->m_PotionParam.m_ContCommonPotionData))
                    return 25;

                nContEffectResult = pObj->InsertPotionContEffect(
                    pApplyPlayer,
                    &pUsePlayer->m_PotionParam.m_ContCommonPotionData[indxDelBuff],
                    pEffecFld,
                    pEffecFld->m_nContEffectSec[0]);
            }

            if (pEffecFld->m_nTempEffectType != -1)
            {
                if (pEffecFld->m_nTempEffectType >= 150 && pEffecFld->m_nTempEffectType < detail::count_orig_effect_func ||
                    pEffecFld->m_nTempEffectType >= detail::count_new_effect_func)
                {
                    nResult = -1;
                }
                else
                {
                    float fValue = 0.0;
                    if (ATF::Global::_GetTempEffectValue(pEffecFld, pEffecFld->m_nTempEffectType, &fValue))
                    {
                        char nRet = -1;
                        auto fnEffect = CPvpPotion::g_TempEffectFunc[pEffecFld->m_nTempEffectType];
                        if (fnEffect && fnEffect(pUsePlayer, pApplyPlayer, fValue, &nRet))
                            nResult = 0;
                        else
                            nResult = nRet;
                    }
                    else
                    {
                        nResult = -1;
                    }
                }
            }

            int result;
            if (nContEffectResult && nResult)
                result = nContEffectResult;
            else
                result = 0;
            return result;
        }
    }
}
<|endoftext|>