Commit 470ade4e authored by Kelvin Rodriguez's avatar Kelvin Rodriguez
Browse files

added some additional functional stuff + meta prgamming utils function

parent c2dcd2b5
Loading
Loading
Loading
Loading
+100 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ from autocnet.graph.node import Node
from autocnet.io import network as io_network
from autocnet.vis.graph_view import plot_graph, cluster_plot


# The total number of pixels squared that can fit into the keys number of GB of RAM for SIFT.
MAXSIZE = {0:None,
           2:6250,
@@ -54,10 +55,14 @@ class CandidateGraph(nx.Graph):
    edge_attr_dict_factory = Edge

    def __init__(self, *args, basepath=None, **kwargs):
        self.edge_attr_dict_factory = decorate_class(Edge, create_cg_updater(self), exclude=['clean', 'get_keypoints'])

        super(CandidateGraph, self).__init__(*args, **kwargs)
        self.graph['node_counter'] = 0
        node_labels = {}
        self.graph['node_name_map'] = {}
        self.points = pd.DataFrame()
        self.nodemask = self.node.keys()

        for node_name in self.nodes():
            image_name = os.path.basename(node_name)
@@ -83,6 +88,12 @@ class CandidateGraph(nx.Graph):
        self.graph['creationdate'] = strftime("%Y-%m-%d %H:%M:%S", gmtime())
        self.graph['modifieddate'] = strftime("%Y-%m-%d %H:%M:%S", gmtime())

        self.points = pd.DataFrame()
        self.pointsmask = pd.DataFrame()

    def get_matches(self, clean_keys=[], edges=[]):
        return self.apply_func_to_edges('get_matches')

    def __eq__(self, other):
        eq = True
        # Check the nodes
@@ -415,7 +426,8 @@ class CandidateGraph(nx.Graph):
        graph_mask_keys : list
                          of keys in graph_masks
        """
        if not isinstance(function, str):
        return_lis = []
        if callable(function):
            function = function.__name__

        for s, d, edge in self.edges_iter(data=True):
@@ -424,7 +436,58 @@ class CandidateGraph(nx.Graph):
            except:
                raise AttributeError(function, ' is not an attribute of Edge')
            else:
                func(*args, **kwargs)
                ret = func(*args, **kwargs)
                return_lis.append(ret)

        if any(return_lis):
            return return_lis


    def apply(self, function, on='edge',out=None, args=(), **kwargs):
        """
        Applys a function to every node or edge, returns collected return
        values.

        TODO: Merge with apply_func_to_edges?

        Parameters
        ----------
        function : callable
                   Function to apply to graph. Should accept (id, data).

        on : string
             Whether to use nodes or edges. default is 'edge'.

        out : var
              Optionally put the output in a variable rather than returning it

        args : iterable
               Some iterable of positional arguments for function.

        kwargs : dict
                 keyword args to pass into function.
        """
        options = {
            'edge' : self.edges_iter,
            'edges' : self.edges_iter,
            'e' : self.edges_iter,
            0 : self.edges_iter,
            'node' : self.nodes_iter,
            'nodes' : self.nodes_iter,
            'n' : self.nodes_iter,
            1 : self.nodes_iter
        }

        if not callable(function):
            raise TypeError('{} is not callable.'.format(function))

        res = []
        for elem in options[on](data=True):
            res.append(function(elem, *args, **kwargs))

        if out: out=res
        else: return res


    def symmetry_checks(self):
        '''
@@ -695,6 +758,41 @@ class CandidateGraph(nx.Graph):
        H.graph = self.graph
        return H

    def subgraph(self, nbunch):
        s = super(CandidateGraph, self)
        sg = s.subgraph(nbunch)
        self.nodemask = sg.nodes()

    def nodes_iter(self, data=False):
        s = super(CandidateGraph, self)
        nodes = s.nodes_iter(data)
        ret = []
        for n in nodes:
            if data:
                if n[0] in self.nodemask:
                    ret.append(n)
            else:
                if n in self.nodemask:
                    ret.append(n)
        return iter(ret)

    # def edges_iter(self, nbunch=[], data=False, key=False):
    #     s = super(CandidateGraph, self)
    #     if not isinstance(nbunch, list):
    #         nbunch = [nbunch]
    #
    #     if nbunch:
    #         nbunch = [node for node in nbunch if nbunch not in list(self.nodemask)]
    #     else:
    #         nbunch = list(self.nodemask)
    #
    #     try:
    #         return s.edges_iter(nbunch=nbunch, data=data)
    #     except:
    #         return s.edges_iter([self.node[node]['image_path'] for node in nbunch], data=data)



    def subgraph_from_matches(self):
        """
        Returns a sub-graph where all edges have matches.
+45 −0
Original line number Diff line number Diff line
@@ -366,3 +366,48 @@ def methodispatch(func):
    wrapper.register = dispatcher.register
    update_wrapper(wrapper, dispatcher)
    return wrapper


def decorate_class(cls, decorator, exclude=[], *args, **kwargs):
    """
    Decorates a class with a give docorator. Returns a subclass with
    dectorations applied

    Parameters
    ----------
    cls : Class
          A class to be decorated

    decorator : callable
                callable to wrap cls's methods with

    exclude : list
              list of method names to exclude from being decorated

    args, kwargs : list, dict
                   Parameters to pass into decorator
    """
    def decorate(cls):
        attributes = cls.__dict__.keys()
        for attr in attributes: # there's propably a better way to do this
            if callable(getattr(cls, attr)):
                name = getattr(cls, attr).__name__
                if name[0] == '_' or name in exclude:
                    continue
                setattr(cls, attr, decorator(getattr(cls, attr)))
        return cls
    # return decorated copy (i.e. a subclass with decorations)
    return decorate(type('cls_copy', cls.__bases__, dict(cls.__dict__)))

def create_cg_updater(cg):
    """
    Create a decorator function using object
    """
    def decorator(func):
        def wrapper(self, *args, **kwargs):
            ret = func(self, *args, **kwargs)
            # do something with cg
            if ret:
                return ret
        return wrapper
    return decorator