<commit_before>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include "reconstructed_regions.hpp"
#include "LocalizationResult.hpp"
#include "ILocalizer.hpp"

#include <openMVG/features/image_describer.hpp>
#include <openMVG/sfm/sfm_data.hpp>
#include <openMVG/sfm/pipelines/localization/SfM_Localizer.hpp>
#include <openMVG/stl/stlMap.hpp>
#include <openMVG/voctree/vocabulary_tree.hpp>
#include <openMVG/voctree/database.hpp>
#include <openMVG/matching/matcher_kdtree_flann.hpp>
#include <openMVG/matching/regions_matcher.hpp>
#include <flann/algorithms/dist.h>

#define USE_SIFT_FLOAT 0

namespace openMVG {
namespace localization {

//@fixme find a better place or maje the class template?
typedef openMVG::features::Descriptor<float, 128> DescriptorFloat;
#if USE_SIFT_FLOAT
typedef Reconstructed_Regions<features::SIOPointFeature, float, 128> Reconstructed_RegionsT;
#else
typedef Reconstructed_Regions<features::SIOPointFeature, unsigned char, 128> Reconstructed_RegionsT;
#endif

class VoctreeLocalizer : public ILocalizer
{

public:
  enum Algorithm : int { FirstBest=0, BestResult=1, AllResults=2, Cluster=3};
  static Algorithm initFromString(const std::string &value);

public:
  struct Parameters : LocalizerParameters
  {

    Parameters() : LocalizerParameters(),
      _useGuidedMatching(false),
      _algorithm(Algorithm::FirstBest),
      _numResults(4),
      _maxResults(10),
      _numCommonViews(3),
      _ccTagUseCuda(true)
    { }

    bool _useGuidedMatching;    //< Enable/disable guided matching when matching images
    Algorithm _algorithm;       //< algorithm to use for localization
    size_t _numResults;         //< number of best matching images to retrieve from the database
    size_t _maxResults;         //< for algorithm AllResults, it stops the image matching when this number of matched images is reached
    size_t _numCommonViews;     //< number minimum common images in which a point must be seen to be used in cluster tracking
    bool _ccTagUseCuda;         //< ccTag-CUDA cannot process frames at different resolutions ATM, so set to false if localizer is used on images of differing sizes
  };

public:

  /**
   * @brief Initialize a localizer based on a vocabulary tree
   *
   * @param[in] sfmFilePath The path to the sfmdata file containing the scene
   * reconstruction.
   * @param[in] descriptorsFolder The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @param[in] vocTreeFilepath The path to the vocabulary tree (usually a .tree file).
   * @param[in] weightsFilepath Optional path to the weights of the vocabulary
   * tree (usually a .weights file), if not provided the weights will be recomputed
   * when all the documents are added.
   * @param[in] useSIFT_CCTAG Optional and enabled only if the CCTAG are available.
   * It enable the use of combined SIFT and CCTAG features.
   */
  VoctreeLocalizer(const std::string &sfmFilePath,
                   const std::string &descriptorsFolder,
                   const std::string &vocTreeFilepath,
                   const std::string &weightsFilepath
#ifdef HAVE_CCTAG
                   , bool useSIFT_CCTAG
#endif
                  );

  /**
   * @brief Just a wrapper around the different localization algorithm, the algorithm
   * used to localized is chosen using \p param._algorithm. This version extract the
   * sift features from the query image.
   *
   * @param[in] imageGrey The input greyscale image.
   * @param[in] param The parameters for the localization.
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration.
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] localizationResult The localization result containing the pose and the associations.
   * @param[in] imagePath Optional complete path to the image, used only for debugging purposes.
   * @return  true if the image has been successfully localized.
   */
  bool localize(const image::Image<unsigned char> & imageGrey,
                const LocalizerParameters *param,
                bool useInputIntrinsics,
                cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                LocalizationResult &localizationResult,
                const std::string& imagePath = std::string());

  /**
   * @brief Just a wrapper around the different localization algorithm, the algorithm
   * used to localized is chosen using \p param._algorithm. This version takes as
   * input the sift feature already extracted.
   *
   * @param[in] genQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization.
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration.
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] localizationResult The localization result containing the pose and the associations.
   * @param[in] imagePath Optional complete path to the image, used only for debugging purposes.
   * @return  true if the image has been successfully localized.
   */
  bool localize(const std::unique_ptr<features::Regions> &genQueryRegions,
                const std::pair<std::size_t, std::size_t> imageSize,
                const LocalizerParameters *param,
                bool useInputIntrinsics,
                cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                LocalizationResult & localizationResult,
                const std::string& imagePath);

  // not yet implemented!
  bool localizeRig(const std::vector<image::Image<unsigned char> > & vec_imageGrey,
                             const LocalizerParameters *param,
                             std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                             const std::vector<geometry::Pose3 > &vec_subPoses,
                             geometry::Pose3 rigPose);

  /**
   * @brief Try to localize an image in the database: it queries the database to
   * retrieve \p numResults matching images and it tries to localize the query image
   * wrt the retrieve images in order of their score taking the first best result.
   *
   * @param[in] siftQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] pose The camera pose
   * @param[out] resection_data the 2D-3D correspondences used to compute the pose
   * @param[out] associationIDs the ids of the 2D-3D correspondences used to compute the pose
   * @return true if the localization is successful
   */
  bool localizeFirstBestResult(const features::SIFT_Regions &siftQueryRegions,
                               const std::pair<std::size_t, std::size_t> imageSize,
                               const Parameters &param,
                               bool useInputIntrinsics,
                               cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                               LocalizationResult &localizationResult,
                               const std::string& imagePath = std::string());

  /**
   * @brief Try to localize an image in the database: it queries the database to
   * retrieve \p numResults matching images and it tries to localize the query image
   * wrt the retrieve images in order of their score, collecting all the 2d-3d correspondences
   * and performing the resection with all these correspondences
   *
   * @param[in] siftQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] pose The camera pose
   * @param[out] resection_data the 2D-3D correspondences used to compute the pose
   * @param[out] associationIDs the ids of the 2D-3D correspondences used to compute the pose
   * @return true if the localization is successful
   */
  bool localizeAllResults(const features::SIFT_Regions &siftQueryRegions,
                          const std::pair<std::size_t, std::size_t> imageSize,
                          const Parameters &param,
                          bool useInputIntrinsics,
                          cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                          LocalizationResult &localizationResult,
                          const std::string& imagePath = std::string());

  void getAllAssociations(const features::SIFT_Regions &siftQueryRegions,
                          const std::pair<std::size_t, std::size_t> imageSize,
                          const Parameters &param,
                          bool useInputIntrinsics,
                          const cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                          std::map< std::pair<IndexT, IndexT>, std::size_t > &occurences,
                          Mat &pt2D,
                          Mat &pt3D,
                          const std::string& imagePath = std::string()) const;

private:
  /**
   * @brief Load the vocabulary tree.

   * @param[in] vocTreeFilepath The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @param[in] weightsFilepath weightsFilepath Optional path to the weights of the vocabulary
   * tree (usually a .weights file), if not provided the weights will be recomputed
   * when all the documents are added.
   * @param[in] feat_directory The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @return true if everything went ok
   */
  bool initDatabase(const std::string & vocTreeFilepath,
                                    const std::string & weightsFilepath,
                                    const std::string & feat_directory);

#if USE_SIFT_FLOAT
  typedef flann::L2<float> MetricT;
  typedef matching::ArrayMatcher_Kdtree_Flann<float, MetricT> MatcherT;
#else
  typedef flann::L2<unsigned char> MetricT;
  typedef matching::ArrayMatcher_Kdtree_Flann<unsigned char, MetricT> MatcherT;
#endif
  bool robustMatching(matching::RegionsMatcherT<MatcherT> & matcher,
                      const cameras::IntrinsicBase * queryIntrinsics,// the intrinsics of the image we are using as reference
                      const Reconstructed_RegionsT & regionsToMatch,
                      const cameras::IntrinsicBase * matchedIntrinsics,
                      const float fDistRatio,
                      const bool b_guided_matching,
                      const std::pair<size_t,size_t> & imageSizeI,     // size of the first image
                      const std::pair<size_t,size_t> & imageSizeJ,     // size of the first image
                      std::vector<matching::IndMatch> & vec_featureMatches) const;

  /**
   * @brief Load all the Descriptors who have contributed to the reconstruction.
   * deprecated.. now inside initDatabase
   */
  bool loadReconstructionDescriptors(
    const sfm::SfM_Data & sfm_data,
    const std::string & feat_directory);

public:

  // for each view index, it contains the features and descriptors that have an
  // associated 3D point
  Hash_Map<IndexT, Reconstructed_RegionsT > _regions_per_view;

  // the feature extractor
  // @fixme do we want a generic image describer?
//  features::SIFT_float_describer _image_describer;
  features::Image_describer* _image_describer;

  // the vocabulary tree used to generate the database and the visual images for
  // the query images
  voctree::VocabularyTree<DescriptorFloat> _voctree;

  // the database that stores the visual word representation of each image of
  // the original dataset
  voctree::Database _database;

};

/**
 * @brief Print the name of the algorithm
 */
std::ostream& operator<<(std::ostream& os, VoctreeLocalizer::Algorithm a);

/**
 * @brief Get the type of algorithm from an integer
 */
std::istream& operator>>(std::istream &in, VoctreeLocalizer::Algorithm &a);

} // localization
} // openMVG
<commit_msg>[localization] changed default algorithm for voctree localizer<commit_after>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include "reconstructed_regions.hpp"
#include "LocalizationResult.hpp"
#include "ILocalizer.hpp"

#include <openMVG/features/image_describer.hpp>
#include <openMVG/sfm/sfm_data.hpp>
#include <openMVG/sfm/pipelines/localization/SfM_Localizer.hpp>
#include <openMVG/stl/stlMap.hpp>
#include <openMVG/voctree/vocabulary_tree.hpp>
#include <openMVG/voctree/database.hpp>
#include <openMVG/matching/matcher_kdtree_flann.hpp>
#include <openMVG/matching/regions_matcher.hpp>
#include <flann/algorithms/dist.h>

#define USE_SIFT_FLOAT 0

namespace openMVG {
namespace localization {

//@fixme find a better place or maje the class template?
typedef openMVG::features::Descriptor<float, 128> DescriptorFloat;
#if USE_SIFT_FLOAT
typedef Reconstructed_Regions<features::SIOPointFeature, float, 128> Reconstructed_RegionsT;
#else
typedef Reconstructed_Regions<features::SIOPointFeature, unsigned char, 128> Reconstructed_RegionsT;
#endif

class VoctreeLocalizer : public ILocalizer
{

public:
  enum Algorithm : int { FirstBest=0, BestResult=1, AllResults=2, Cluster=3};
  static Algorithm initFromString(const std::string &value);

public:
  struct Parameters : LocalizerParameters
  {

    Parameters() : LocalizerParameters(),
      _useGuidedMatching(false),
      _algorithm(Algorithm::AllResults),
      _numResults(4),
      _maxResults(10),
      _numCommonViews(3),
      _ccTagUseCuda(true)
    { }

    bool _useGuidedMatching;    //< Enable/disable guided matching when matching images
    Algorithm _algorithm;       //< algorithm to use for localization
    size_t _numResults;         //< number of best matching images to retrieve from the database
    size_t _maxResults;         //< for algorithm AllResults, it stops the image matching when this number of matched images is reached
    size_t _numCommonViews;     //< number minimum common images in which a point must be seen to be used in cluster tracking
    bool _ccTagUseCuda;         //< ccTag-CUDA cannot process frames at different resolutions ATM, so set to false if localizer is used on images of differing sizes
  };

public:

  /**
   * @brief Initialize a localizer based on a vocabulary tree
   *
   * @param[in] sfmFilePath The path to the sfmdata file containing the scene
   * reconstruction.
   * @param[in] descriptorsFolder The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @param[in] vocTreeFilepath The path to the vocabulary tree (usually a .tree file).
   * @param[in] weightsFilepath Optional path to the weights of the vocabulary
   * tree (usually a .weights file), if not provided the weights will be recomputed
   * when all the documents are added.
   * @param[in] useSIFT_CCTAG Optional and enabled only if the CCTAG are available.
   * It enable the use of combined SIFT and CCTAG features.
   */
  VoctreeLocalizer(const std::string &sfmFilePath,
                   const std::string &descriptorsFolder,
                   const std::string &vocTreeFilepath,
                   const std::string &weightsFilepath
#ifdef HAVE_CCTAG
                   , bool useSIFT_CCTAG
#endif
                  );

  /**
   * @brief Just a wrapper around the different localization algorithm, the algorithm
   * used to localized is chosen using \p param._algorithm. This version extract the
   * sift features from the query image.
   *
   * @param[in] imageGrey The input greyscale image.
   * @param[in] param The parameters for the localization.
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration.
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] localizationResult The localization result containing the pose and the associations.
   * @param[in] imagePath Optional complete path to the image, used only for debugging purposes.
   * @return  true if the image has been successfully localized.
   */
  bool localize(const image::Image<unsigned char> & imageGrey,
                const LocalizerParameters *param,
                bool useInputIntrinsics,
                cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                LocalizationResult &localizationResult,
                const std::string& imagePath = std::string());

  /**
   * @brief Just a wrapper around the different localization algorithm, the algorithm
   * used to localized is chosen using \p param._algorithm. This version takes as
   * input the sift feature already extracted.
   *
   * @param[in] genQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization.
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration.
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] localizationResult The localization result containing the pose and the associations.
   * @param[in] imagePath Optional complete path to the image, used only for debugging purposes.
   * @return  true if the image has been successfully localized.
   */
  bool localize(const std::unique_ptr<features::Regions> &genQueryRegions,
                const std::pair<std::size_t, std::size_t> imageSize,
                const LocalizerParameters *param,
                bool useInputIntrinsics,
                cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                LocalizationResult & localizationResult,
                const std::string& imagePath);

  // not yet implemented!
  bool localizeRig(const std::vector<image::Image<unsigned char> > & vec_imageGrey,
                             const LocalizerParameters *param,
                             std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                             const std::vector<geometry::Pose3 > &vec_subPoses,
                             geometry::Pose3 rigPose);

  /**
   * @brief Try to localize an image in the database: it queries the database to
   * retrieve \p numResults matching images and it tries to localize the query image
   * wrt the retrieve images in order of their score taking the first best result.
   *
   * @param[in] siftQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] pose The camera pose
   * @param[out] resection_data the 2D-3D correspondences used to compute the pose
   * @param[out] associationIDs the ids of the 2D-3D correspondences used to compute the pose
   * @return true if the localization is successful
   */
  bool localizeFirstBestResult(const features::SIFT_Regions &siftQueryRegions,
                               const std::pair<std::size_t, std::size_t> imageSize,
                               const Parameters &param,
                               bool useInputIntrinsics,
                               cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                               LocalizationResult &localizationResult,
                               const std::string& imagePath = std::string());

  /**
   * @brief Try to localize an image in the database: it queries the database to
   * retrieve \p numResults matching images and it tries to localize the query image
   * wrt the retrieve images in order of their score, collecting all the 2d-3d correspondences
   * and performing the resection with all these correspondences
   *
   * @param[in] siftQueryRegions The input features of the query image
   * @param[in] imageSize The size of the input image
   * @param[in] param The parameters for the localization
   * @param[in] useInputIntrinsics Uses the \p queryIntrinsics as known calibration
   * @param[in,out] queryIntrinsics Intrinsic parameters of the camera, they are used if the
   * flag useInputIntrinsics is set to true, otherwise they are estimated from the correspondences.
   * @param[out] pose The camera pose
   * @param[out] resection_data the 2D-3D correspondences used to compute the pose
   * @param[out] associationIDs the ids of the 2D-3D correspondences used to compute the pose
   * @return true if the localization is successful
   */
  bool localizeAllResults(const features::SIFT_Regions &siftQueryRegions,
                          const std::pair<std::size_t, std::size_t> imageSize,
                          const Parameters &param,
                          bool useInputIntrinsics,
                          cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                          LocalizationResult &localizationResult,
                          const std::string& imagePath = std::string());

  void getAllAssociations(const features::SIFT_Regions &siftQueryRegions,
                          const std::pair<std::size_t, std::size_t> imageSize,
                          const Parameters &param,
                          bool useInputIntrinsics,
                          const cameras::Pinhole_Intrinsic_Radial_K3 &queryIntrinsics,
                          std::map< std::pair<IndexT, IndexT>, std::size_t > &occurences,
                          Mat &pt2D,
                          Mat &pt3D,
                          const std::string& imagePath = std::string()) const;

private:
  /**
   * @brief Load the vocabulary tree.

   * @param[in] vocTreeFilepath The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @param[in] weightsFilepath weightsFilepath Optional path to the weights of the vocabulary
   * tree (usually a .weights file), if not provided the weights will be recomputed
   * when all the documents are added.
   * @param[in] feat_directory The path to the directory containing the features
   * of the scene (.desc and .feat files).
   * @return true if everything went ok
   */
  bool initDatabase(const std::string & vocTreeFilepath,
                                    const std::string & weightsFilepath,
                                    const std::string & feat_directory);

#if USE_SIFT_FLOAT
  typedef flann::L2<float> MetricT;
  typedef matching::ArrayMatcher_Kdtree_Flann<float, MetricT> MatcherT;
#else
  typedef flann::L2<unsigned char> MetricT;
  typedef matching::ArrayMatcher_Kdtree_Flann<unsigned char, MetricT> MatcherT;
#endif
  bool robustMatching(matching::RegionsMatcherT<MatcherT> & matcher,
                      const cameras::IntrinsicBase * queryIntrinsics,// the intrinsics of the image we are using as reference
                      const Reconstructed_RegionsT & regionsToMatch,
                      const cameras::IntrinsicBase * matchedIntrinsics,
                      const float fDistRatio,
                      const bool b_guided_matching,
                      const std::pair<size_t,size_t> & imageSizeI,     // size of the first image
                      const std::pair<size_t,size_t> & imageSizeJ,     // size of the first image
                      std::vector<matching::IndMatch> & vec_featureMatches) const;

  /**
   * @brief Load all the Descriptors who have contributed to the reconstruction.
   * deprecated.. now inside initDatabase
   */
  bool loadReconstructionDescriptors(
    const sfm::SfM_Data & sfm_data,
    const std::string & feat_directory);

public:

  // for each view index, it contains the features and descriptors that have an
  // associated 3D point
  Hash_Map<IndexT, Reconstructed_RegionsT > _regions_per_view;

  // the feature extractor
  // @fixme do we want a generic image describer?
//  features::SIFT_float_describer _image_describer;
  features::Image_describer* _image_describer;

  // the vocabulary tree used to generate the database and the visual images for
  // the query images
  voctree::VocabularyTree<DescriptorFloat> _voctree;

  // the database that stores the visual word representation of each image of
  // the original dataset
  voctree::Database _database;

};

/**
 * @brief Print the name of the algorithm
 */
std::ostream& operator<<(std::ostream& os, VoctreeLocalizer::Algorithm a);

/**
 * @brief Get the type of algorithm from an integer
 */
std::istream& operator>>(std::istream &in, VoctreeLocalizer::Algorithm &a);

} // localization
} // openMVG
<|endoftext|>


<commit_before>
#include "bci.hpp"
#include "fake_bci.hpp"
#include "nonblocking_bci.hpp"

#include <boost/python.hpp>
#include <stdint.h>

using namespace boost::python;

class BCIPythonWrap : public BCI, public wrapper<BCI>
{
public:
    BCIPythonWrap(BCI* pBCI) : mpBCI(pBCI) {

    }

    virtual ~BCIPythonWrap() {
        delete mpBCI;
    }

    bool open(uint8_t mac[]) {
        return this->get_override("open")(mac);
    }

    bool init(size_t channels) {
        return this->get_override("init")(channels);
    }

    bool start() {
        return this->get_override("start")();
    }

    size_t acquire() {
        return this->get_override("acquire")();
        return 0;
    }

    void getdata(uint32_t* data, size_t n) {
        this->get_override("getdata")(data, n);
    }

    uint64_t timestamp() {
        return this->get_override("timestamp")();
        return 0;
    }

    bool stop() {
        return this->get_override("stop")();
    }

    bool close() {
        return this->get_override("close")();
    }

private:
    BCI* mpBCI;
};

BCI* create_fake_bci() {
    return new BCIPythonWrap(new FakeBCI());
}

BCI* create_enobio_bci() {
    return create_fake_bci();
}

BOOST_PYTHON_MODULE(boosted_bci)
{
    def("create_fake_bci", create_fake_bci, return_value_policy<manage_new_object>());
    def("create_enobio_bci", create_enobio_bci, return_value_policy<manage_new_object>());

    class_<BCIPythonWrap, boost::noncopyable>("BCI", no_init)
        .def("open", pure_virtual(&BCI::open))
        .def("init", pure_virtual(&BCI::init))
        .def("start", pure_virtual(&BCI::start))
        .def("acquire", pure_virtual(&BCI::acquire))
        .def("getdata", pure_virtual(&BCI::getdata))
        .def("timestamp", pure_virtual(&BCI::timestamp))
        .def("stop", pure_virtual(&BCI::stop))
        .def("close", pure_virtual(&BCI::close))
    ;

    class_<NonblockingBCI, bases<BCI> >("NonblockingBCI", init<BCI*>())
        .def("open", &NonblockingBCI::open)
        .def("init", &NonblockingBCI::init)
        .def("start", &NonblockingBCI::start)
        .def("acquire", &NonblockingBCI::acquire)
        .def("getdata", &NonblockingBCI::getdata)
        .def("timestamp", &NonblockingBCI::timestamp)
        .def("stop", &NonblockingBCI::stop)
        .def("close", &NonblockingBCI::close)
        ;
}

<commit_msg>Added channels method to the Python wrapper interface<commit_after>
#include "bci.hpp"
#include "fake_bci.hpp"
#include "nonblocking_bci.hpp"

#include <boost/python.hpp>
#include <stdint.h>

using namespace boost::python;

class BCIPythonWrap : public BCI, public wrapper<BCI>
{
public:
    BCIPythonWrap(BCI* pBCI) : mpBCI(pBCI) {

    }

    virtual ~BCIPythonWrap() {
        delete mpBCI;
    }

    bool open(uint8_t mac[]) {
        return this->get_override("open")(mac);
    }

    bool init(size_t channels) {
        return this->get_override("init")(channels);
    }

    size_t channels() {
        return this->get_override("channels")();
    }

    bool start() {
        return this->get_override("start")();
    }

    size_t acquire() {
        return this->get_override("acquire")();
        return 0;
    }

    void getdata(uint32_t* data, size_t n) {
        this->get_override("getdata")(data, n);
    }

    uint64_t timestamp() {
        return this->get_override("timestamp")();
        return 0;
    }

    bool stop() {
        return this->get_override("stop")();
    }

    bool close() {
        return this->get_override("close")();
    }

private:
    BCI* mpBCI;
};

BCI* create_fake_bci() {
    return new BCIPythonWrap(new FakeBCI());
}

BCI* create_enobio_bci() {
    return create_fake_bci();
}

BOOST_PYTHON_MODULE(boosted_bci)
{
    def("create_fake_bci", create_fake_bci, return_value_policy<manage_new_object>());
    def("create_enobio_bci", create_enobio_bci, return_value_policy<manage_new_object>());

    class_<BCIPythonWrap, boost::noncopyable>("BCI", no_init)
        .def("open", pure_virtual(&BCI::open))
        .def("init", pure_virtual(&BCI::init))
        .def("channels", pure_virtual(&BCI::channels))
        .def("start", pure_virtual(&BCI::start))
        .def("acquire", pure_virtual(&BCI::acquire))
        .def("getdata", pure_virtual(&BCI::getdata))
        .def("timestamp", pure_virtual(&BCI::timestamp))
        .def("stop", pure_virtual(&BCI::stop))
        .def("close", pure_virtual(&BCI::close))
    ;

    class_<NonblockingBCI, bases<BCI> >("NonblockingBCI", init<BCI*>())
        .def("open", &NonblockingBCI::open)
        .def("init", &NonblockingBCI::init)
        .def("channels", &NonblockingBCI::channels)
        .def("start", &NonblockingBCI::start)
        .def("acquire", &NonblockingBCI::acquire)
        .def("getdata", &NonblockingBCI::getdata)
        .def("timestamp", &NonblockingBCI::timestamp)
        .def("stop", &NonblockingBCI::stop)
        .def("close", &NonblockingBCI::close)
        ;
}

<|endoftext|>


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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

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

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

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

#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbImage.h"
#include "otbMeanDifferenceImageFilter.h"
#include "otbCommandProgressUpdate.h"

int otbMeanDiffChangeDetectionTest(int argc, char* argv[] )
{

  if( argc < 5 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile1 inputImageFile2  radius outputImageFile " << std::endl;
    return -1;
    }

  // Define the dimension of the images
  const unsigned int Dimension = 2;

  // Declare the types of the images
  typedef double InternalPixelType;
  typedef double OutputPixelType;
  typedef otb::Image<InternalPixelType, Dimension>  InputImageType1;
  typedef otb::Image<InternalPixelType, Dimension>  InputImageType2;
  typedef otb::Image<InternalPixelType, Dimension>  ChangeImageType;
  typedef otb::Image<OutputPixelType, Dimension>  OutputImageType;

  typedef otb::ImageFileReader< InputImageType1 >  ReaderType1;
  typedef otb::ImageFileReader< InputImageType2 >  ReaderType2;
  typedef otb::ImageFileWriter< OutputImageType >  WriterType;
  typedef itk::RescaleIntensityImageFilter< ChangeImageType,
                                            OutputImageType > RescalerType;

  // Declare the type for the filter
  typedef otb::MeanDifferenceImageFilter<
                                InputImageType1,
                                InputImageType2,
                                ChangeImageType  >       FilterType;

  ReaderType1::Pointer reader1 = ReaderType1::New();
  ReaderType2::Pointer reader2 = ReaderType2::New();
  WriterType::Pointer writer = WriterType::New();
  FilterType::Pointer   filter = FilterType::New();
  RescalerType::Pointer rescaler = RescalerType::New();

  const char * inputFilename1  = argv[1];
  const char * inputFilename2  = argv[2];
  const char * outputFilename = argv[4];

  reader1->SetFileName( inputFilename1  );
  reader2->SetFileName( inputFilename2  );
  writer->SetFileName( outputFilename );
  rescaler->SetOutputMinimum( itk::NumericTraits< OutputPixelType >::min());
  rescaler->SetOutputMaximum( itk::NumericTraits< OutputPixelType >::max());

  filter->SetInput1( reader1->GetOutput() );
  filter->SetInput2( reader2->GetOutput() );
  filter->SetRadius( atoi(argv[3]) );

  rescaler->SetInput( filter->GetOutput() );
  writer->SetInput( rescaler->GetOutput() );

  typedef otb::CommandProgressUpdate<FilterType> CommandType;

  CommandType::Pointer observer = CommandType::New();
  filter->AddObserver(itk::ProgressEvent(), observer);

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

  return 0;

}

<commit_msg>correction étalement de la dynamique.<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

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

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

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

#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbImage.h"
#include "otbMeanDifferenceImageFilter.h"
#include "otbCommandProgressUpdate.h"

int otbMeanDiffChangeDetectionTest(int argc, char* argv[] )
{

  if( argc < 5 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile1 inputImageFile2  radius outputImageFile " << std::endl;
    return -1;
    }

  // Define the dimension of the images
  const unsigned int Dimension = 2;

  // Declare the types of the images
  typedef double InternalPixelType;
  typedef double OutputPixelType;
  typedef otb::Image<InternalPixelType, Dimension>  InputImageType1;
  typedef otb::Image<InternalPixelType, Dimension>  InputImageType2;
  typedef otb::Image<InternalPixelType, Dimension>  ChangeImageType;
  typedef otb::Image<OutputPixelType, Dimension>  OutputImageType;

  typedef otb::ImageFileReader< InputImageType1 >  ReaderType1;
  typedef otb::ImageFileReader< InputImageType2 >  ReaderType2;
  typedef otb::ImageFileWriter< OutputImageType >  WriterType;
  typedef itk::RescaleIntensityImageFilter< ChangeImageType,
                                            OutputImageType > RescalerType;

  // Declare the type for the filter
  typedef otb::MeanDifferenceImageFilter<
                                InputImageType1,
                                InputImageType2,
                                ChangeImageType  >       FilterType;

  ReaderType1::Pointer reader1 = ReaderType1::New();
  ReaderType2::Pointer reader2 = ReaderType2::New();
  WriterType::Pointer writer = WriterType::New();
  FilterType::Pointer   filter = FilterType::New();
  RescalerType::Pointer rescaler = RescalerType::New();

  const char * inputFilename1  = argv[1];
  const char * inputFilename2  = argv[2];
  const char * outputFilename = argv[4];

  reader1->SetFileName( inputFilename1  );
  reader2->SetFileName( inputFilename2  );
  writer->SetFileName( outputFilename );
  rescaler->SetOutputMinimum( -1 );
  rescaler->SetOutputMaximum( 1 );

  filter->SetInput1( reader1->GetOutput() );
  filter->SetInput2( reader2->GetOutput() );
  filter->SetRadius( atoi(argv[3]) );

  rescaler->SetInput( filter->GetOutput() );
  writer->SetInput( rescaler->GetOutput() );

  typedef otb::CommandProgressUpdate<FilterType> CommandType;

  CommandType::Pointer observer = CommandType::New();
  filter->AddObserver(itk::ProgressEvent(), observer);

  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    std::cout << "ExceptionObject caught !" << std::endl;
    std::cout << err << std::endl;
    return -1;
    }

  return 0;

}

<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultivariateLegendrePolynomialTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

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

#include "itkMultivariateLegendrePolynomial.h"

/**
 *  This test exercise the functionality of the
 *
 *  itk::MultivariateLegendrePolynomial  class
 *
 *
 */

int itkMultivariateLegendrePolynomialTest(int , char* [] )
{

  typedef itk::MultivariateLegendrePolynomial PolynomialType;

  const unsigned int dimension = 3;
  const unsigned int degree    = 3;

  PolynomialType::DomainSizeType domainSize(dimension);

  PolynomialType polynomial( dimension, degree, domainSize );

  return 0;
}

<commit_msg><commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMultivariateLegendrePolynomialTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#include <iostream>

#include "itkMultivariateLegendrePolynomial.h"

/**
 *  This test exercise the functionality of the
 *
 *  itk::MultivariateLegendrePolynomial  class
 *
 */

int itkMultivariateLegendrePolynomialTest(int , char* [] )
{

  typedef itk::MultivariateLegendrePolynomial PolynomialType;

  const unsigned int dimension = 3;
  const unsigned int degree    = 3;

  PolynomialType::DomainSizeType domainSize(dimension);

  PolynomialType polynomial( dimension, degree, domainSize );

  if ( polynomial.GetDimension() != dimension )
    {
    std::cout << "Test fails: GetDimension()" << std::endl ;
    return EXIT_FAILURE ;
    }

  if ( polynomial.GetDegree() != degree )
    {
    std::cout << "Test fails: GetDegree()" << std::endl ;
    return EXIT_FAILURE ;
    }

  if ( polynomial.GetDomainSize() != domainSize )
    {
    std::cout << "Test fails: GetDomainSize()" << std::endl ;
    return EXIT_FAILURE ;
    }

  if ( polynomial.GetNumberOfCoefficients() != 20 )
    {
    std::cout << "Test fails: GetNumberOfCoefficients()" << std::endl ;
    return EXIT_FAILURE ;
    }

  PolynomialType::CoefficientArrayType  coefficients(20) ;

  coefficients.Fill( 0.1 ) ;

  try
    {
    polynomial.SetCoefficients( coefficients ) ;
    }
  catch ( ... )
    {
    }

  PolynomialType::SimpleForwardIterator bIter( &polynomial ) ;
  bIter.Begin() ;
  while (!bIter.IsAtEnd())
    {
    bIter.Get() ;
    ++bIter ;
    }

  std::cout << "Test succeeded." << std::endl;
  return EXIT_SUCCESS ;
}

<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//
// "Copyright Centre National d'Etudes Spatiales"
// "Copyright Centre for Remote Imaging, Sensing and Processing"
//
// License:  LGPL
//
// See LICENSE.txt file in the top level directory for more details.
//
//----------------------------------------------------------------------------
// $Id$

#include <AlosPalsar/AlosPalsarLeader.h>
#include <AlosPalsar/AlosPalsarLeaderFactory.h>
#include <AlosPalsar/AlosPalsarRecordHeader.h>

#include <AlosPalsar/AlosPalsarFileDescriptor.h>
#include <AlosPalsar/AlosPalsarDataSetSummary.h>
#include <AlosPalsar/AlosPalsarFacilityData.h>

#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimKeywordNames.h>

// Static trace for debugging
static ossimTrace traceDebug("ossimAlosPalsarLeader:debug");

namespace ossimplugins
{

const int AlosPalsarLeader::AlosPalsarFacilityDataID = 17;
const int AlosPalsarLeader::AlosPalsarRadiometricDataID = 5;
const int AlosPalsarLeader::AlosPalsarPlatformPositionDataID = 3;
// const int AlosPalsarLeader::AlosPalsarMapProjectionDataID = 3; //
const int AlosPalsarLeader::AlosPalsarDataSetSummaryID = 2;
const int AlosPalsarLeader::AlosPalsarFileDescriptorID = 1;

AlosPalsarLeader::AlosPalsarLeader()
{
}

AlosPalsarLeader::~AlosPalsarLeader()
{
  ClearRecords();
}

std::ostream& operator<<(std::ostream& os, const AlosPalsarLeader& data)
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = data._records.begin();
  while (it != data._records.end())
  {
    (*it).second->Write(os);
    ++it;
  }
  return os;

}

std::istream& operator>>(std::istream& is, AlosPalsarLeader& data)
{
  AlosPalsarLeaderFactory factory;

  data.ClearRecords();

  AlosPalsarRecordHeader header;
  bool eof = false;
  while (!eof)
  {
    is >> header;
    if (is.eof())
    {
      eof = true;
    }
    else
    {
      AlosPalsarRecord* record = factory.Instanciate(header.get_rec_seq());
      if (record != NULL)
      {
        record->Read(is);
        data._records[header.get_rec_seq()] = record;
      }
      else
      {
        char* buff = new char[header.get_length()-12];
        is.read(buff, header.get_length() - 12);
        delete buff;
      }
    }
  }
  return is;
}

AlosPalsarLeader::AlosPalsarLeader(const AlosPalsarLeader& rhs)
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
  while (it != rhs._records.end())
  {
    _records[(*it).first] = (*it).second->Clone();
    ++it;
  }
}

AlosPalsarLeader& AlosPalsarLeader::operator=(const AlosPalsarLeader& rhs)
{
  ClearRecords();
  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
  while (it != rhs._records.end())
  {
    _records[(*it).first] = (*it).second->Clone();
    ++it;
  }

  return *this;
}

void AlosPalsarLeader::ClearRecords()
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = _records.begin();
  while (it != _records.end())
  {
    delete(*it).second;
    ++it;
  }
  _records.clear();
}

bool AlosPalsarLeader::saveState(ossimKeywordlist& kwl,
                                 const char* prefix) const
{

  static const char MODULE[] = "AlosPalsarLeader::saveState";

  if (traceDebug())
  {
    ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
  }

  bool result = true;

  char name[64];

  //kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAlosPalsarModel", true);
  /*
   * Adding metadata necessary to the sensor model in the keywordlist
   */
  const AlosPalsarFileDescriptor *leaderfiledesc = get_AlosPalsarFileDescriptor();
  if (leaderfiledesc != NULL)
  {
    kwl.add(prefix, "filename", leaderfiledesc->get_file_name().c_str(), true);
  }
  else
  {
    result = false;
  }

  /*
   * Adding metadata necessary to the sensor model in the keywordlist
   */
  const AlosPalsarDataSetSummary *datasetSummary = get_AlosPalsarDataSetSummary();
  if ((datasetSummary != NULL) && (result == true))
  {
    kwl.add(prefix, "inp_sctim", (datasetSummary->get_inp_sctim()).c_str(), true);
    kwl.add(prefix, "ellip_maj", datasetSummary->get_ellip_maj(), true);
    kwl.add(prefix, "ellip_min", datasetSummary->get_ellip_min(), true);
    kwl.add(prefix, "sc_lin", datasetSummary->get_sc_lin(), true);
    kwl.add(prefix, "sc_pix", datasetSummary->get_sc_pix(), true);
    kwl.add(prefix, "wave_length", datasetSummary->get_wave_length(), true);
    kwl.add(prefix, "fr", datasetSummary->get_fr(), true);
    kwl.add(prefix, "fa", datasetSummary->get_fa(), true);
    kwl.add(prefix, "time_dir_pix", (datasetSummary->get_time_dir_pix()).c_str(), true);
    kwl.add(prefix, "time_dir_lin", (datasetSummary->get_time_dir_lin()).c_str(), true);
    kwl.add(prefix, "line_spacing", datasetSummary->get_line_spacing(), true);
    kwl.add(prefix, "pix_spacing", datasetSummary->get_pix_spacing(), true);
    kwl.add(prefix, "nlooks_az", datasetSummary->get_n_azilok(), true);
    kwl.add(prefix, "n_rnglok", datasetSummary->get_n_rnglok(), true);
    kwl.add(prefix, "alt_dopcen[0]", datasetSummary->get_alt_dopcen()[0], true);
    kwl.add(prefix, "crt_dopcen[0]", datasetSummary->get_crt_dopcen()[0], true);
    kwl.add(prefix, "crt_dopcen[1]", datasetSummary->get_crt_dopcen()[1], true);
    kwl.add(prefix, "dopcen_range[0]", datasetSummary->get_dopcen_range()[0], true);
    kwl.add(prefix, "dopcen_range[1]", datasetSummary->get_dopcen_range()[1], true);
    //FIXME check if those data are available
//     kwl.add(prefix, "zero_dop_range_time_f_pixel", datasetSummary->get_zero_dop_range_time_f_pixel(),true);
//     kwl.add(prefix, "zero_dop_range_time_c_pixel", datasetSummary->get_zero_dop_range_time_c_pixel(),true);
//     kwl.add(prefix, "zero_dop_range_time_l_pixel", datasetSummary->get_zero_dop_range_time_l_pixel(),true);
  }
  else
  {
    result = false;
  }

  // FIXME do not handle Alos map projection information for now...
//   const AlosPalsarMapProjectionData *mapprojectiondata = get_AlosPalsarMapProjectionData();
//   if ( (mapprojectiondata != NULL) && (result == true) )
//   {
//     kwl.add(prefix, "map_proj_des",(mapprojectiondata->get_map_proj_des()).c_str(),true);
//     kwl.add(prefix, "num_lines",(double) mapprojectiondata->get_num_lines(),true);
//     kwl.add(prefix, "num_pix",(double) mapprojectiondata->get_num_pix_in_line(),true);
//     kwl.add(prefix, "first_line_first_pixel_lat",mapprojectiondata->get_first_line_first_pixel_lat(), true);
//     kwl.add(prefix, "first_line_first_pixel_lon",mapprojectiondata->get_first_line_first_pixel_lon(), true);
//     kwl.add(prefix, "first_line_last_pixel_lat",mapprojectiondata->get_first_line_last_pixel_lat(), true);
//     kwl.add(prefix, "first_line_last_pixel_lon",mapprojectiondata->get_first_line_last_pixel_lon(), true);
//     kwl.add(prefix, "last_line_first_pixel_lat",mapprojectiondata->get_last_line_first_pixel_lat(), true);
//     kwl.add(prefix, "last_line_first_pixel_lon",mapprojectiondata->get_last_line_first_pixel_lon(), true);
//     kwl.add(prefix, "last_line_last_pixel_lat",mapprojectiondata->get_last_line_last_pixel_lat(), true);
//     kwl.add(prefix, "last_line_last_pixel_lon",mapprojectiondata->get_last_line_last_pixel_lon(), true);
//   }
//   else
//   {
//     result = false;
//   }

  const AlosPalsarPlatformPositionData *platformposition = get_AlosPalsarPlatformPositionData();
  if ((platformposition != NULL) && (result == true))
  {
    kwl.add(prefix, "neph", platformposition->get_ndata(), true);
    kwl.add(prefix, "eph_year", platformposition->get_year(), true);
    kwl.add(prefix, "eph_month", platformposition->get_month(), true);
    kwl.add(prefix, "eph_day", platformposition->get_day(), true);
    kwl.add(prefix, "eph_gmt_day", platformposition->get_gmt_day(), true);
    kwl.add(prefix, "eph_sec", platformposition->get_gmt_sec(), true);
    kwl.add(prefix, "eph_hr_angle", platformposition->get_hr_angle(), true);
    kwl.add(prefix, "eph_int", platformposition->get_data_int(), true);

    for (int i = 0; i < platformposition->get_ndata(); i++)
    {
      sprintf(name, "eph%i_posX", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[0], true);
      sprintf(name, "eph%i_posY", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[1], true);
      sprintf(name, "eph%i_posZ", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[2], true);

      sprintf(name, "eph%i_velX", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[0], true);
      sprintf(name, "eph%i_velY", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[1], true);
      sprintf(name, "eph%i_velZ", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[2], true);
    }
  }
  else
  {
    result = false;
  }

  const AlosPalsarRadiometricData *radiometricdata = get_AlosPalsarRadiometricData();
  if ((radiometricdata != NULL) && (result == true))
  {
    kwl.add(prefix, "calibration_factor", radiometricdata->get_calibration_factor(), true);
  }
  else
  {
    result = false;
  }

  // FIXME  Do not handle Palsar facility-related data for now...
  // The current code corresponds to the ERS facility-related data
  // which is completely different from that for PALSAR
  /*
  const AlosPalsarFacilityData *facilitydata = get_AlosPalsarFacilityData();
  if ((facilitydata != NULL) && (result == true))
  {
    kwl.add(prefix, "coef_ground_range_1", facilitydata->get_coef_ground_range_1(), true);
    kwl.add(prefix, "coef_ground_range_2", facilitydata->get_coef_ground_range_2(), true);
    kwl.add(prefix, "coef_ground_range_3", facilitydata->get_coef_ground_range_3(), true);
    kwl.add(prefix, "coef_ground_range_4", facilitydata->get_coef_ground_range_4(), true);
  }
  else
  {
    result = false;
  }
  */

  if (traceDebug())
  {
    ossimNotify(ossimNotifyLevel_DEBUG)
    << MODULE << " exit status = " << (result ? "true" : "false\n")
    << std::endl;
  }

  return result;
}

const AlosPalsarFacilityData * AlosPalsarLeader::get_AlosPalsarFacilityData() const
{
//   return const_cast<const AlosPalsarFacilityData*>(dynamic_cast<AlosPalsarFacilityData*>(_records[AlosPalsarFacilityDataID]));
//   RecordType::const_iterator it = _records.find(AlosPalsarFacilityDataID)->second;
//   return dynamic_cast<const AlosPalsarFacilityData*>(it.find(AlosPalsarFacilityDataID));
  return dynamic_cast<const AlosPalsarFacilityData*>(_records.find(AlosPalsarFacilityDataID)->second);
}

const AlosPalsarRadiometricData * AlosPalsarLeader::get_AlosPalsarRadiometricData() const
{
  return dynamic_cast<const AlosPalsarRadiometricData*>(_records.find(AlosPalsarRadiometricDataID)->second);
}

const AlosPalsarPlatformPositionData * AlosPalsarLeader::get_AlosPalsarPlatformPositionData() const
{
  return dynamic_cast<const AlosPalsarPlatformPositionData*>(_records.find(AlosPalsarPlatformPositionDataID)->second);
}

/*
const AlosPalsarMapProjectionData * AlosPalsarLeader::get_AlosPalsarMapProjectionData() const
{
//   return (AlosPalsarMapProjectionData*)_records[AlosPalsarMapProjectionDataID];
  return dynamic_cast<const AlosPalsarMapProjectionData*>(_records.find(AlosPalsarMapProjectionDataID)->second);
}
*/
// no map projection data for level 1.1

const AlosPalsarDataSetSummary * AlosPalsarLeader::get_AlosPalsarDataSetSummary() const
{
  return dynamic_cast<const AlosPalsarDataSetSummary*>(_records.find(AlosPalsarDataSetSummaryID)->second);
}

const AlosPalsarFileDescriptor * AlosPalsarLeader::get_AlosPalsarFileDescriptor() const
{
  return dynamic_cast<const AlosPalsarFileDescriptor*>(_records.find(AlosPalsarFileDescriptorID)->second);
}

}
<commit_msg>BUG: fix new/delete mismatch in ossim Palsar plugin<commit_after>//----------------------------------------------------------------------------
//
// "Copyright Centre National d'Etudes Spatiales"
// "Copyright Centre for Remote Imaging, Sensing and Processing"
//
// License:  LGPL
//
// See LICENSE.txt file in the top level directory for more details.
//
//----------------------------------------------------------------------------
// $Id$

#include <AlosPalsar/AlosPalsarLeader.h>
#include <AlosPalsar/AlosPalsarLeaderFactory.h>
#include <AlosPalsar/AlosPalsarRecordHeader.h>

#include <AlosPalsar/AlosPalsarFileDescriptor.h>
#include <AlosPalsar/AlosPalsarDataSetSummary.h>
#include <AlosPalsar/AlosPalsarFacilityData.h>

#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimKeywordNames.h>

// Static trace for debugging
static ossimTrace traceDebug("ossimAlosPalsarLeader:debug");

namespace ossimplugins
{

const int AlosPalsarLeader::AlosPalsarFacilityDataID = 17;
const int AlosPalsarLeader::AlosPalsarRadiometricDataID = 5;
const int AlosPalsarLeader::AlosPalsarPlatformPositionDataID = 3;
// const int AlosPalsarLeader::AlosPalsarMapProjectionDataID = 3; //
const int AlosPalsarLeader::AlosPalsarDataSetSummaryID = 2;
const int AlosPalsarLeader::AlosPalsarFileDescriptorID = 1;

AlosPalsarLeader::AlosPalsarLeader()
{
}

AlosPalsarLeader::~AlosPalsarLeader()
{
  ClearRecords();
}

std::ostream& operator<<(std::ostream& os, const AlosPalsarLeader& data)
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = data._records.begin();
  while (it != data._records.end())
  {
    (*it).second->Write(os);
    ++it;
  }
  return os;

}

std::istream& operator>>(std::istream& is, AlosPalsarLeader& data)
{
  AlosPalsarLeaderFactory factory;

  data.ClearRecords();

  AlosPalsarRecordHeader header;
  bool eof = false;
  while (!eof)
  {
    is >> header;
    if (is.eof())
    {
      eof = true;
    }
    else
    {
      AlosPalsarRecord* record = factory.Instanciate(header.get_rec_seq());
      if (record != NULL)
      {
        record->Read(is);
        data._records[header.get_rec_seq()] = record;
      }
      else
      {
        if (header.get_length() > 12)
          {
          char* buff = new char[header.get_length()-12];
          is.read(buff, header.get_length() - 12);
          delete [] buff;
          }
      }
    }
  }
  return is;
}

AlosPalsarLeader::AlosPalsarLeader(const AlosPalsarLeader& rhs)
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
  while (it != rhs._records.end())
  {
    _records[(*it).first] = (*it).second->Clone();
    ++it;
  }
}

AlosPalsarLeader& AlosPalsarLeader::operator=(const AlosPalsarLeader& rhs)
{
  ClearRecords();
  std::map<int, AlosPalsarRecord*>::const_iterator it = rhs._records.begin();
  while (it != rhs._records.end())
  {
    _records[(*it).first] = (*it).second->Clone();
    ++it;
  }

  return *this;
}

void AlosPalsarLeader::ClearRecords()
{
  std::map<int, AlosPalsarRecord*>::const_iterator it = _records.begin();
  while (it != _records.end())
  {
    delete(*it).second;
    ++it;
  }
  _records.clear();
}

bool AlosPalsarLeader::saveState(ossimKeywordlist& kwl,
                                 const char* prefix) const
{

  static const char MODULE[] = "AlosPalsarLeader::saveState";

  if (traceDebug())
  {
    ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
  }

  bool result = true;

  char name[64];

  //kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAlosPalsarModel", true);
  /*
   * Adding metadata necessary to the sensor model in the keywordlist
   */
  const AlosPalsarFileDescriptor *leaderfiledesc = get_AlosPalsarFileDescriptor();
  if (leaderfiledesc != NULL)
  {
    kwl.add(prefix, "filename", leaderfiledesc->get_file_name().c_str(), true);
  }
  else
  {
    result = false;
  }

  /*
   * Adding metadata necessary to the sensor model in the keywordlist
   */
  const AlosPalsarDataSetSummary *datasetSummary = get_AlosPalsarDataSetSummary();
  if ((datasetSummary != NULL) && (result == true))
  {
    kwl.add(prefix, "inp_sctim", (datasetSummary->get_inp_sctim()).c_str(), true);
    kwl.add(prefix, "ellip_maj", datasetSummary->get_ellip_maj(), true);
    kwl.add(prefix, "ellip_min", datasetSummary->get_ellip_min(), true);
    kwl.add(prefix, "sc_lin", datasetSummary->get_sc_lin(), true);
    kwl.add(prefix, "sc_pix", datasetSummary->get_sc_pix(), true);
    kwl.add(prefix, "wave_length", datasetSummary->get_wave_length(), true);
    kwl.add(prefix, "fr", datasetSummary->get_fr(), true);
    kwl.add(prefix, "fa", datasetSummary->get_fa(), true);
    kwl.add(prefix, "time_dir_pix", (datasetSummary->get_time_dir_pix()).c_str(), true);
    kwl.add(prefix, "time_dir_lin", (datasetSummary->get_time_dir_lin()).c_str(), true);
    kwl.add(prefix, "line_spacing", datasetSummary->get_line_spacing(), true);
    kwl.add(prefix, "pix_spacing", datasetSummary->get_pix_spacing(), true);
    kwl.add(prefix, "nlooks_az", datasetSummary->get_n_azilok(), true);
    kwl.add(prefix, "n_rnglok", datasetSummary->get_n_rnglok(), true);
    kwl.add(prefix, "alt_dopcen[0]", datasetSummary->get_alt_dopcen()[0], true);
    kwl.add(prefix, "crt_dopcen[0]", datasetSummary->get_crt_dopcen()[0], true);
    kwl.add(prefix, "crt_dopcen[1]", datasetSummary->get_crt_dopcen()[1], true);
    kwl.add(prefix, "dopcen_range[0]", datasetSummary->get_dopcen_range()[0], true);
    kwl.add(prefix, "dopcen_range[1]", datasetSummary->get_dopcen_range()[1], true);
    //FIXME check if those data are available
//     kwl.add(prefix, "zero_dop_range_time_f_pixel", datasetSummary->get_zero_dop_range_time_f_pixel(),true);
//     kwl.add(prefix, "zero_dop_range_time_c_pixel", datasetSummary->get_zero_dop_range_time_c_pixel(),true);
//     kwl.add(prefix, "zero_dop_range_time_l_pixel", datasetSummary->get_zero_dop_range_time_l_pixel(),true);
  }
  else
  {
    result = false;
  }

  // FIXME do not handle Alos map projection information for now...
//   const AlosPalsarMapProjectionData *mapprojectiondata = get_AlosPalsarMapProjectionData();
//   if ( (mapprojectiondata != NULL) && (result == true) )
//   {
//     kwl.add(prefix, "map_proj_des",(mapprojectiondata->get_map_proj_des()).c_str(),true);
//     kwl.add(prefix, "num_lines",(double) mapprojectiondata->get_num_lines(),true);
//     kwl.add(prefix, "num_pix",(double) mapprojectiondata->get_num_pix_in_line(),true);
//     kwl.add(prefix, "first_line_first_pixel_lat",mapprojectiondata->get_first_line_first_pixel_lat(), true);
//     kwl.add(prefix, "first_line_first_pixel_lon",mapprojectiondata->get_first_line_first_pixel_lon(), true);
//     kwl.add(prefix, "first_line_last_pixel_lat",mapprojectiondata->get_first_line_last_pixel_lat(), true);
//     kwl.add(prefix, "first_line_last_pixel_lon",mapprojectiondata->get_first_line_last_pixel_lon(), true);
//     kwl.add(prefix, "last_line_first_pixel_lat",mapprojectiondata->get_last_line_first_pixel_lat(), true);
//     kwl.add(prefix, "last_line_first_pixel_lon",mapprojectiondata->get_last_line_first_pixel_lon(), true);
//     kwl.add(prefix, "last_line_last_pixel_lat",mapprojectiondata->get_last_line_last_pixel_lat(), true);
//     kwl.add(prefix, "last_line_last_pixel_lon",mapprojectiondata->get_last_line_last_pixel_lon(), true);
//   }
//   else
//   {
//     result = false;
//   }

  const AlosPalsarPlatformPositionData *platformposition = get_AlosPalsarPlatformPositionData();
  if ((platformposition != NULL) && (result == true))
  {
    kwl.add(prefix, "neph", platformposition->get_ndata(), true);
    kwl.add(prefix, "eph_year", platformposition->get_year(), true);
    kwl.add(prefix, "eph_month", platformposition->get_month(), true);
    kwl.add(prefix, "eph_day", platformposition->get_day(), true);
    kwl.add(prefix, "eph_gmt_day", platformposition->get_gmt_day(), true);
    kwl.add(prefix, "eph_sec", platformposition->get_gmt_sec(), true);
    kwl.add(prefix, "eph_hr_angle", platformposition->get_hr_angle(), true);
    kwl.add(prefix, "eph_int", platformposition->get_data_int(), true);

    for (int i = 0; i < platformposition->get_ndata(); i++)
    {
      sprintf(name, "eph%i_posX", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[0], true);
      sprintf(name, "eph%i_posY", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[1], true);
      sprintf(name, "eph%i_posZ", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_pos()[2], true);

      sprintf(name, "eph%i_velX", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[0], true);
      sprintf(name, "eph%i_velY", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[1], true);
      sprintf(name, "eph%i_velZ", i);
      kwl.add(prefix, name, (platformposition->get_pos_vect()[i]).get_vel()[2], true);
    }
  }
  else
  {
    result = false;
  }

  const AlosPalsarRadiometricData *radiometricdata = get_AlosPalsarRadiometricData();
  if ((radiometricdata != NULL) && (result == true))
  {
    kwl.add(prefix, "calibration_factor", radiometricdata->get_calibration_factor(), true);
  }
  else
  {
    result = false;
  }

  // FIXME  Do not handle Palsar facility-related data for now...
  // The current code corresponds to the ERS facility-related data
  // which is completely different from that for PALSAR
  /*
  const AlosPalsarFacilityData *facilitydata = get_AlosPalsarFacilityData();
  if ((facilitydata != NULL) && (result == true))
  {
    kwl.add(prefix, "coef_ground_range_1", facilitydata->get_coef_ground_range_1(), true);
    kwl.add(prefix, "coef_ground_range_2", facilitydata->get_coef_ground_range_2(), true);
    kwl.add(prefix, "coef_ground_range_3", facilitydata->get_coef_ground_range_3(), true);
    kwl.add(prefix, "coef_ground_range_4", facilitydata->get_coef_ground_range_4(), true);
  }
  else
  {
    result = false;
  }
  */

  if (traceDebug())
  {
    ossimNotify(ossimNotifyLevel_DEBUG)
    << MODULE << " exit status = " << (result ? "true" : "false\n")
    << std::endl;
  }

  return result;
}

const AlosPalsarFacilityData * AlosPalsarLeader::get_AlosPalsarFacilityData() const
{
//   return const_cast<const AlosPalsarFacilityData*>(dynamic_cast<AlosPalsarFacilityData*>(_records[AlosPalsarFacilityDataID]));
//   RecordType::const_iterator it = _records.find(AlosPalsarFacilityDataID)->second;
//   return dynamic_cast<const AlosPalsarFacilityData*>(it.find(AlosPalsarFacilityDataID));
  return dynamic_cast<const AlosPalsarFacilityData*>(_records.find(AlosPalsarFacilityDataID)->second);
}

const AlosPalsarRadiometricData * AlosPalsarLeader::get_AlosPalsarRadiometricData() const
{
  return dynamic_cast<const AlosPalsarRadiometricData*>(_records.find(AlosPalsarRadiometricDataID)->second);
}

const AlosPalsarPlatformPositionData * AlosPalsarLeader::get_AlosPalsarPlatformPositionData() const
{
  return dynamic_cast<const AlosPalsarPlatformPositionData*>(_records.find(AlosPalsarPlatformPositionDataID)->second);
}

/*
const AlosPalsarMapProjectionData * AlosPalsarLeader::get_AlosPalsarMapProjectionData() const
{
//   return (AlosPalsarMapProjectionData*)_records[AlosPalsarMapProjectionDataID];
  return dynamic_cast<const AlosPalsarMapProjectionData*>(_records.find(AlosPalsarMapProjectionDataID)->second);
}
*/
// no map projection data for level 1.1

const AlosPalsarDataSetSummary * AlosPalsarLeader::get_AlosPalsarDataSetSummary() const
{
  return dynamic_cast<const AlosPalsarDataSetSummary*>(_records.find(AlosPalsarDataSetSummaryID)->second);
}

const AlosPalsarFileDescriptor * AlosPalsarLeader::get_AlosPalsarFileDescriptor() const
{
  return dynamic_cast<const AlosPalsarFileDescriptor*>(_records.find(AlosPalsarFileDescriptorID)->second);
}

}
<|endoftext|>


<commit_before>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// 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.
//

#pragma once

#include "pipeline/guard.hpp"
#include "pipeline/topic_mapper.hpp"
#include "pipeline/transform.hpp"
#include "ruby_entity.hpp"
#include "ruby_observation.hpp"
#include "ruby_pipeline.hpp"

namespace mtconnect::ruby {
  using namespace mtconnect::pipeline;
  using namespace std::literals;
  using namespace date::literals;
  using namespace entity;
  using namespace observation;

  class RubyTransform : public pipeline::Transform
  {
  public:
    static void initialize(mrb_state *mrb, RClass *module)
    {
      auto transClass = mrb_define_class_under(mrb, module, "Transform", mrb->object_class);
      MRB_SET_INSTANCE_TT(transClass, MRB_TT_DATA);
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "CONTINUE"),
                     mrb_int_value(mrb, CONTINUE));
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "RUN"), mrb_int_value(mrb, RUN));
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "SKIP"), mrb_int_value(mrb, SKIP));

      mrb_define_method(
          mrb, transClass, "transform",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap(mrb, self);

            EntityPtr *ent;
            mrb_get_args(mrb, "d", &ent, MRubySharedPtr<Entity>::type());
            auto r = (*trans)(*ent);
            return MRubySharedPtr<Entity>::wrap(mrb, "Entity", r);
          },
          MRB_ARGS_REQ(1));

      auto rubyTrans = mrb_define_class_under(mrb, module, "RubyTransform", transClass);
      MRB_SET_INSTANCE_TT(transClass, MRB_TT_DATA);

      mrb_define_method(
          mrb, rubyTrans, "initialize",
          [](mrb_state *mrb, mrb_value self) {
            const char *name;
            mrb_value gv, block = mrb_nil_value();
            string guard;

            auto c = mrb_get_args(mrb, "z|o&", &name, &gv, &block);
            if (c == 1)
              guard = "Entity";
            else
              guard = stringFromRuby(mrb, gv);

            auto trans = make_shared<RubyTransform>(mrb, self, name, guard);
            if (mrb_block_given_p(mrb))
            {
              trans->m_block = block;
              mrb_gc_register(mrb, block);
            }
            MRubySharedPtr<Transform>::replace(mrb, self, trans);

            return self;
          },
          MRB_ARGS_ARG(1, 1) | MRB_ARGS_BLOCK());

      mrb_define_method(
          mrb, rubyTrans, "forward",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap<RubyTransform>(mrb, self);

            EntityPtr *ent;
            mrb_get_args(mrb, "d", &ent, MRubySharedPtr<Entity>::type());
            auto nxt = trans->next(*ent);
            return MRubySharedPtr<Entity>::wrap(mrb, "Entity", nxt);
          },
          MRB_ARGS_REQ(1));

      mrb_define_method(
          mrb, rubyTrans, "guard=",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap<RubyTransform>(mrb, self);
            mrb_value block;
            const char *guard;
            if (mrb_get_args(mrb, "z&", &guard, &block) > 0)
            {
              trans->m_guardString = guard;
            }

            if (mrb_block_given_p(mrb))
            {
              trans->m_guardBlock = block;
              mrb_gc_register(mrb, block);
            }
            trans->setGuard();

            return self;
          },
          MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
    }

    RubyTransform(mrb_state *mrb, mrb_value self, const std::string &name, const string &guard)
      : Transform(name),
        m_self(self),
        m_method(mrb_intern_lit(mrb, "transform")),
        m_block(mrb_nil_value()),
        m_guardString(guard),
        m_guardBlock(mrb_nil_value())
    {
      setGuard();
    }

    ~RubyTransform()
    {
      std::lock_guard guard(RubyVM::rubyVM());

      auto mrb = RubyVM::rubyVM().state();

      mrb_gc_unregister(mrb, m_self);
      m_self = mrb_nil_value();
      if (!mrb_nil_p(m_block))
        mrb_gc_unregister(mrb, m_block);
      if (!mrb_nil_p(m_guardBlock))
        mrb_gc_unregister(mrb, m_guardBlock);
      m_block = mrb_nil_value();
      m_guardBlock = mrb_nil_value();
    }

    void setMethod(mrb_sym sym) { m_method = sym; }

    void setGuard()
    {
      if (m_guardString == "Observation")
        m_guard = TypeGuard<Observation>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Sample")
        m_guard = TypeGuard<Sample>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Event")
        m_guard = TypeGuard<Event>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Tokens")
        m_guard = TypeGuard<pipeline::Tokens>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Message")
        m_guard = TypeGuard<PipelineMessage>(RUN) || TypeGuard<Entity>(SKIP);
      else
        m_guard = TypeGuard<Entity>(RUN);

      if (!mrb_nil_p(m_guardBlock))
      {
        m_guard = [this, old = m_guard](const entity::EntityPtr entity) -> GuardAction {
          using namespace entity;
          using namespace observation;
          std::lock_guard guard(RubyVM::rubyVM());

          auto mrb = RubyVM::rubyVM().state();
          int save = mrb_gc_arena_save(mrb);

          mrb_value ev = MRubySharedPtr<Entity>::wrap(mrb, "Entity", entity);

          mrb_bool state = false;
          mrb_value values[] = {m_guardBlock, ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 2, values);
          mrb_value rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value block = mrb_ary_ref(mrb, data, 0);
                mrb_value ev = mrb_ary_ref(mrb, data, 1);

                return mrb_yield(mrb, block, ev);
              },
              data, &state);

          if (state)
          {
            LOG(error) << "Error in guard: " << mrb_str_to_cstr(mrb, mrb_inspect(mrb, rv));
            rv = mrb_nil_value();
          }

          mrb_gc_arena_restore(mrb, save);
          if (!mrb_nil_p(rv))
          {
            return GuardAction(mrb_fixnum(rv));
          }
          else
          {
            return old(entity);
          }
        };
      }
    }

    using calldata = pair<RubyTransform *, EntityPtr>;

    const entity::EntityPtr operator()(const entity::EntityPtr entity) override
    {
      NAMED_SCOPE("RubyTransform::operator()");

      using namespace entity;
      using namespace observation;

      EntityPtr res;

      std::lock_guard guard(RubyVM::rubyVM());
      auto mrb = RubyVM::rubyVM().state();
      int save = mrb_gc_arena_save(mrb);

      try
      {
        mrb_value ev;
        const char *klass = "Entity";
        Entity *ptr = entity.get();
        if (dynamic_cast<Observation *>(ptr) != nullptr)
          klass = "Observation";
        else if (dynamic_cast<pipeline::Timestamped *>(ptr) != nullptr)
          klass = "Timestamped";
        else if (dynamic_cast<pipeline::Tokens *>(ptr) != nullptr)
          klass = "Tokens";

        ev = MRubySharedPtr<Entity>::wrap(mrb, klass, entity);
        mrb_value rv;

        mrb_bool state = false;
        if (!mrb_nil_p(m_block))
        {
          mrb_value values[] = {m_self, m_block, ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 3, values);
          rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value self = mrb_ary_ref(mrb, data, 0);
                mrb_value block = mrb_ary_ref(mrb, data, 1);
                mrb_value ev = mrb_ary_ref(mrb, data, 2);
                return mrb_yield_with_class(mrb, block, 1, &ev, self, mrb_class(mrb, self));
              },
              data, &state);
        }
        else
        {
          mrb_value values[] = {m_self, mrb_symbol_value(m_method), ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 3, values);
          rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value self = mrb_ary_ref(mrb, data, 0);
                mrb_sym method = mrb_symbol(mrb_ary_ref(mrb, data, 1));
                mrb_value ev = mrb_ary_ref(mrb, data, 2);
                return mrb_funcall_id(mrb, self, method, 1, ev);
              },
              data, &state);
        }
        if (state)
        {
          LOG(error) << "Error in transform: " << mrb_str_to_cstr(mrb, mrb_inspect(mrb, rv));
          rv = mrb_nil_value();
        }

        if (!mrb_nil_p(rv))
          res = MRubySharedPtr<Entity>::unwrap(rv);
      }
      catch (std::exception e)
      {
        LOG(error) << "Exception thrown in transform" << e.what();
      }
      catch (...)
      {
        LOG(error) << "Unknown Exception thrown in transform";
      }

      mrb_gc_arena_restore(mrb, save);
      return res;
    }

    auto &object() { return m_self; }
    void setObject(mrb_value obj) { m_self = obj; }

  protected:
    PipelineContract *m_contract;
    mrb_value m_self;
    mrb_sym m_method;
    mrb_value m_block;
    std::string m_guardString;
    mrb_value m_guardBlock;
  };
}  // namespace mtconnect::ruby
<commit_msg>Added check for ruby vm in transform destructor<commit_after>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// 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.
//

#pragma once

#include "pipeline/guard.hpp"
#include "pipeline/topic_mapper.hpp"
#include "pipeline/transform.hpp"
#include "ruby_entity.hpp"
#include "ruby_observation.hpp"
#include "ruby_pipeline.hpp"

namespace mtconnect::ruby {
  using namespace mtconnect::pipeline;
  using namespace std::literals;
  using namespace date::literals;
  using namespace entity;
  using namespace observation;

  class RubyTransform : public pipeline::Transform
  {
  public:
    static void initialize(mrb_state *mrb, RClass *module)
    {
      auto transClass = mrb_define_class_under(mrb, module, "Transform", mrb->object_class);
      MRB_SET_INSTANCE_TT(transClass, MRB_TT_DATA);
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "CONTINUE"),
                     mrb_int_value(mrb, CONTINUE));
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "RUN"), mrb_int_value(mrb, RUN));
      mrb_mod_cv_set(mrb, transClass, mrb_intern_check_cstr(mrb, "SKIP"), mrb_int_value(mrb, SKIP));

      mrb_define_method(
          mrb, transClass, "transform",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap(mrb, self);

            EntityPtr *ent;
            mrb_get_args(mrb, "d", &ent, MRubySharedPtr<Entity>::type());
            auto r = (*trans)(*ent);
            return MRubySharedPtr<Entity>::wrap(mrb, "Entity", r);
          },
          MRB_ARGS_REQ(1));

      auto rubyTrans = mrb_define_class_under(mrb, module, "RubyTransform", transClass);
      MRB_SET_INSTANCE_TT(transClass, MRB_TT_DATA);

      mrb_define_method(
          mrb, rubyTrans, "initialize",
          [](mrb_state *mrb, mrb_value self) {
            const char *name;
            mrb_value gv, block = mrb_nil_value();
            string guard;

            auto c = mrb_get_args(mrb, "z|o&", &name, &gv, &block);
            if (c == 1)
              guard = "Entity";
            else
              guard = stringFromRuby(mrb, gv);

            auto trans = make_shared<RubyTransform>(mrb, self, name, guard);
            if (mrb_block_given_p(mrb))
            {
              trans->m_block = block;
              mrb_gc_register(mrb, block);
            }
            MRubySharedPtr<Transform>::replace(mrb, self, trans);

            return self;
          },
          MRB_ARGS_ARG(1, 1) | MRB_ARGS_BLOCK());

      mrb_define_method(
          mrb, rubyTrans, "forward",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap<RubyTransform>(mrb, self);

            EntityPtr *ent;
            mrb_get_args(mrb, "d", &ent, MRubySharedPtr<Entity>::type());
            auto nxt = trans->next(*ent);
            return MRubySharedPtr<Entity>::wrap(mrb, "Entity", nxt);
          },
          MRB_ARGS_REQ(1));

      mrb_define_method(
          mrb, rubyTrans, "guard=",
          [](mrb_state *mrb, mrb_value self) {
            auto trans = MRubySharedPtr<Transform>::unwrap<RubyTransform>(mrb, self);
            mrb_value block;
            const char *guard;
            if (mrb_get_args(mrb, "z&", &guard, &block) > 0)
            {
              trans->m_guardString = guard;
            }

            if (mrb_block_given_p(mrb))
            {
              trans->m_guardBlock = block;
              mrb_gc_register(mrb, block);
            }
            trans->setGuard();

            return self;
          },
          MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
    }

    RubyTransform(mrb_state *mrb, mrb_value self, const std::string &name, const string &guard)
      : Transform(name),
        m_self(self),
        m_method(mrb_intern_lit(mrb, "transform")),
        m_block(mrb_nil_value()),
        m_guardString(guard),
        m_guardBlock(mrb_nil_value())
    {
      setGuard();
    }

    ~RubyTransform()
    {
      std::lock_guard guard(RubyVM::rubyVM());

      if (&RubyVM::rubyVM())
      {
        auto mrb = RubyVM::rubyVM().state();

        mrb_gc_unregister(mrb, m_self);
        m_self = mrb_nil_value();
        if (!mrb_nil_p(m_block))
          mrb_gc_unregister(mrb, m_block);
        if (!mrb_nil_p(m_guardBlock))
          mrb_gc_unregister(mrb, m_guardBlock);
        m_block = mrb_nil_value();
        m_guardBlock = mrb_nil_value();
      }
    }

    void setMethod(mrb_sym sym) { m_method = sym; }

    void setGuard()
    {
      if (m_guardString == "Observation")
        m_guard = TypeGuard<Observation>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Sample")
        m_guard = TypeGuard<Sample>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Event")
        m_guard = TypeGuard<Event>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Tokens")
        m_guard = TypeGuard<pipeline::Tokens>(RUN) || TypeGuard<Entity>(SKIP);
      else if (m_guardString == "Message")
        m_guard = TypeGuard<PipelineMessage>(RUN) || TypeGuard<Entity>(SKIP);
      else
        m_guard = TypeGuard<Entity>(RUN);

      if (!mrb_nil_p(m_guardBlock))
      {
        m_guard = [this, old = m_guard](const entity::EntityPtr entity) -> GuardAction {
          using namespace entity;
          using namespace observation;
          std::lock_guard guard(RubyVM::rubyVM());

          auto mrb = RubyVM::rubyVM().state();
          int save = mrb_gc_arena_save(mrb);

          mrb_value ev = MRubySharedPtr<Entity>::wrap(mrb, "Entity", entity);

          mrb_bool state = false;
          mrb_value values[] = {m_guardBlock, ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 2, values);
          mrb_value rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value block = mrb_ary_ref(mrb, data, 0);
                mrb_value ev = mrb_ary_ref(mrb, data, 1);

                return mrb_yield(mrb, block, ev);
              },
              data, &state);

          if (state)
          {
            LOG(error) << "Error in guard: " << mrb_str_to_cstr(mrb, mrb_inspect(mrb, rv));
            rv = mrb_nil_value();
          }

          mrb_gc_arena_restore(mrb, save);
          if (!mrb_nil_p(rv))
          {
            return GuardAction(mrb_fixnum(rv));
          }
          else
          {
            return old(entity);
          }
        };
      }
    }

    using calldata = pair<RubyTransform *, EntityPtr>;

    const entity::EntityPtr operator()(const entity::EntityPtr entity) override
    {
      NAMED_SCOPE("RubyTransform::operator()");

      using namespace entity;
      using namespace observation;

      EntityPtr res;

      std::lock_guard guard(RubyVM::rubyVM());
      auto mrb = RubyVM::rubyVM().state();
      int save = mrb_gc_arena_save(mrb);

      try
      {
        mrb_value ev;
        const char *klass = "Entity";
        Entity *ptr = entity.get();
        if (dynamic_cast<Observation *>(ptr) != nullptr)
          klass = "Observation";
        else if (dynamic_cast<pipeline::Timestamped *>(ptr) != nullptr)
          klass = "Timestamped";
        else if (dynamic_cast<pipeline::Tokens *>(ptr) != nullptr)
          klass = "Tokens";

        ev = MRubySharedPtr<Entity>::wrap(mrb, klass, entity);
        mrb_value rv;

        mrb_bool state = false;
        if (!mrb_nil_p(m_block))
        {
          mrb_value values[] = {m_self, m_block, ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 3, values);
          rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value self = mrb_ary_ref(mrb, data, 0);
                mrb_value block = mrb_ary_ref(mrb, data, 1);
                mrb_value ev = mrb_ary_ref(mrb, data, 2);
                return mrb_yield_with_class(mrb, block, 1, &ev, self, mrb_class(mrb, self));
              },
              data, &state);
        }
        else
        {
          mrb_value values[] = {m_self, mrb_symbol_value(m_method), ev};
          mrb_value data = mrb_ary_new_from_values(mrb, 3, values);
          rv = mrb_protect(
              mrb,
              [](mrb_state *mrb, mrb_value data) {
                mrb_value self = mrb_ary_ref(mrb, data, 0);
                mrb_sym method = mrb_symbol(mrb_ary_ref(mrb, data, 1));
                mrb_value ev = mrb_ary_ref(mrb, data, 2);
                return mrb_funcall_id(mrb, self, method, 1, ev);
              },
              data, &state);
        }
        if (state)
        {
          LOG(error) << "Error in transform: " << mrb_str_to_cstr(mrb, mrb_inspect(mrb, rv));
          rv = mrb_nil_value();
        }

        if (!mrb_nil_p(rv))
          res = MRubySharedPtr<Entity>::unwrap(rv);
      }
      catch (std::exception e)
      {
        LOG(error) << "Exception thrown in transform" << e.what();
      }
      catch (...)
      {
        LOG(error) << "Unknown Exception thrown in transform";
      }

      mrb_gc_arena_restore(mrb, save);
      return res;
    }

    auto &object() { return m_self; }
    void setObject(mrb_value obj) { m_self = obj; }

  protected:
    PipelineContract *m_contract;
    mrb_value m_self;
    mrb_sym m_method;
    mrb_value m_block;
    std::string m_guardString;
    mrb_value m_guardBlock;
  };
}  // namespace mtconnect::ruby
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <windows.h>
#include "include/debug.h"
#include "include/util.h"

namespace yappy {
namespace debug {

namespace {

bool s_debugOut = false;
bool s_consoleOut = false;
bool s_fileOut = false;

HANDLE s_hFile = INVALID_HANDLE_VALUE;

}

bool enableDebugOutput() noexcept
{
	s_debugOut = true;
	return s_debugOut;
}

bool enableConsoleOutput() noexcept
{
	if (s_consoleOut) {
		return s_consoleOut;
	}
	BOOL ret = ::AllocConsole();
	if (ret) {
		s_consoleOut = true;
	}
	return s_consoleOut;
}

bool enableFileOutput(const wchar_t *fileName) noexcept
{
	if (s_fileOut) {
		return s_fileOut;
	}
	HANDLE h = ::CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
	if (h != INVALID_HANDLE_VALUE) {
		s_fileOut = true;
		s_hFile = h;
	}
	return s_fileOut;
}

void shutdownDebugOutput() noexcept
{
	s_debugOut = false;

	if (s_consoleOut) {
		::FreeConsole();
	}
	s_consoleOut = false;

	if (s_hFile != INVALID_HANDLE_VALUE) {
		::CloseHandle(s_hFile);
	}
	s_fileOut = false;
}

void write(const wchar_t *str, bool newline) noexcept
{
	// Debug Out
	if (s_debugOut) {
		::OutputDebugString(str);
		if (newline) {
			::OutputDebugString(L"\n");
		}
	}
	// Console Out
	if (s_consoleOut) {
		HANDLE hOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
		DWORD len = static_cast<DWORD>(wcslen(str));
		DWORD written = 0;
		::WriteConsole(hOut, str, len, &written, NULL);
		if (newline) {
			::WriteConsole(hOut, L"\n", 1, &written, NULL);
		}
	}
	// File Out
	if (s_fileOut) {
		std::string mbstr = util::wc2utf8(str);
		if (newline) {
			mbstr += "\n";
		}
		DWORD written = 0;
		::WriteFile(s_hFile, mbstr.c_str(), static_cast<DWORD>(mbstr.size()), &written, NULL);
		::FlushFileBuffers(s_hFile);
	}
}

void writef(const wchar_t *fmt, ...) noexcept
{
	va_list args;
	va_start(args, fmt);
	wchar_t buf[1024];
	_vsnwprintf_s(buf, _TRUNCATE, fmt, args);
	va_end(args);

	write(buf, true);
}

}
}
<commit_msg>No flush in debug output<commit_after>#include "stdafx.h"
#include <windows.h>
#include "include/debug.h"
#include "include/util.h"

namespace yappy {
namespace debug {

namespace {

bool s_debugOut = false;
bool s_consoleOut = false;
bool s_fileOut = false;

HANDLE s_hFile = INVALID_HANDLE_VALUE;

}

bool enableDebugOutput() noexcept
{
	s_debugOut = true;
	return s_debugOut;
}

bool enableConsoleOutput() noexcept
{
	if (s_consoleOut) {
		return s_consoleOut;
	}
	BOOL ret = ::AllocConsole();
	if (ret) {
		s_consoleOut = true;
	}
	return s_consoleOut;
}

bool enableFileOutput(const wchar_t *fileName) noexcept
{
	if (s_fileOut) {
		return s_fileOut;
	}
	HANDLE h = ::CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
	if (h != INVALID_HANDLE_VALUE) {
		s_fileOut = true;
		s_hFile = h;
	}
	return s_fileOut;
}

void shutdownDebugOutput() noexcept
{
	s_debugOut = false;

	if (s_consoleOut) {
		::FreeConsole();
	}
	s_consoleOut = false;

	if (s_hFile != INVALID_HANDLE_VALUE) {
		::CloseHandle(s_hFile);
	}
	s_fileOut = false;
}

void write(const wchar_t *str, bool newline) noexcept
{
	// Debug Out
	if (s_debugOut) {
		::OutputDebugString(str);
		if (newline) {
			::OutputDebugString(L"\n");
		}
	}
	// Console Out
	if (s_consoleOut) {
		HANDLE hOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
		DWORD len = static_cast<DWORD>(wcslen(str));
		DWORD written = 0;
		::WriteConsole(hOut, str, len, &written, NULL);
		if (newline) {
			::WriteConsole(hOut, L"\n", 1, &written, NULL);
		}
	}
	// File Out
	if (s_fileOut) {
		std::string mbstr = util::wc2utf8(str);
		if (newline) {
			mbstr += "\n";
		}
		DWORD written = 0;
		::WriteFile(s_hFile, mbstr.c_str(), static_cast<DWORD>(mbstr.size()), &written, NULL);
	}
}

void writef(const wchar_t *fmt, ...) noexcept
{
	va_list args;
	va_start(args, fmt);
	wchar_t buf[1024];
	_vsnwprintf_s(buf, _TRUNCATE, fmt, args);
	va_end(args);

	write(buf, true);
}

}
}
<|endoftext|>