bindings/python/rips.h
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 04 Aug 2009 13:23:16 -0700
branchdev
changeset 156 f75fb57d2831
parent 130 580eaa850c4f
permissions -rw-r--r--
Changed implementation of WeightedRips to store simplex values (max distance between simplices' vertices) as an invisible layer on top of each simplex object, so that the data() field of WeightedRips has been freed for use by the users again.

#ifndef __PYTHON_RIPS_H__
#define __PYTHON_RIPS_H__

#include <topology/rips.h>
#include <utilities/indirect.h>

#include "simplex.h"

#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>


namespace bp = boost::python;


namespace dionysus { 
namespace python   {

// This strange wrapper is necessary because Rips<...> stores only a const reference to the distances. 
// Something on the C++ side of things must store the actual DistancesWrapper object, and that's the 
// purpose of this class.
class RipsWithDistances
{
    public:
        class DistancesWrapper
        {
            public:
                typedef             unsigned                                        IndexType;
                typedef             double                                          DistanceType;
        
                                    DistancesWrapper(bp::object distances):
                                        distances_(distances)                       {}
        
                DistanceType        operator()(IndexType a, IndexType b) const      { return bp::extract<DistanceType>(distances_(a, b)); }
        
                IndexType           size() const                                    { return bp::len(distances_); }
                IndexType           begin() const                                   { return 0; }
                IndexType           end() const                                     { return size(); }
        
            private:
                bp::object          distances_;
        };

        typedef             DistancesWrapper::IndexType                             IndexType;
        typedef             DistancesWrapper::DistanceType                          DistanceType;

        typedef             Rips<DistancesWrapper, SimplexVD>                       RipsDS;
        typedef             RipsDS::Comparison                                      Comparison;
        typedef             RipsDS::Evaluator                                       Evaluator;

        class FunctorWrapper
        {
            public:
                                    FunctorWrapper(bp::object functor):
                                        functor_(functor)                           {}
        
                void                operator()(const RipsDS::Simplex& s) const      { functor_(s); }
        
            private:
                bp::object          functor_;
        };


                            RipsWithDistances(bp::object distances):
                                distances_(distances), rips_(distances_),
                                cmp_(Comparison(distances_)), eval_(distances_)     {}

        void                generate(Dimension k, DistanceType max, bp::object functor) const
        { rips_.generate(k, max, FunctorWrapper(functor)); }

        void                vertex_cofaces(IndexType v, Dimension k, DistanceType max, bp::object functor) const
        { rips_.vertex_cofaces(v, k, max, FunctorWrapper(functor)); }
        
        void                edge_cofaces(IndexType u, IndexType v, Dimension k, DistanceType max, bp::object functor) const
        { rips_.edge_cofaces(u, v, k, max, FunctorWrapper(functor)); }

        void                generate_candidates(Dimension k, DistanceType max, bp::object functor, bp::object seq) const
        { 
            rips_.generate(k, max, FunctorWrapper(functor), 
                           bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }
        
        void                vertex_cofaces_candidate(IndexType v, Dimension k, DistanceType max, 
                                                     bp::object functor, bp::object seq) const
        { 
            rips_.vertex_cofaces(v, k, max, FunctorWrapper(functor), 
                                 bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }
        
        void                edge_cofaces_candidates(IndexType u, IndexType v, Dimension k, DistanceType max, 
                                                    bp::object functor, bp::object seq) const
        { 
            rips_.edge_cofaces(u, v, k, max, FunctorWrapper(functor), 
                               bp::stl_input_iterator<IndexType>(seq), bp::stl_input_iterator<IndexType>());
        }

        int                 cmp(const SimplexObject& s1, const SimplexObject& s2) const                     { return cmp_native(s1, s2); }
        int                 cmp_native(const SimplexVD& s1, const SimplexVD& s2) const                      { return cmp_.compare(s1, s2); }
        
        DistanceType        eval(const SimplexObject& s) const                                              { return eval_native(s); }
        DistanceType        eval_native(const SimplexVD& s) const                                           { return eval_(s); }
        
    private:
        DistancesWrapper                            distances_;
        RipsDS                                      rips_;
        ThreeOutcomeCompare<Comparison>             cmp_;           // in Python, cmp is a three outcome comparison
        Evaluator                                   eval_;
};

} } // namespace dionysus::python

#endif