{"action":"created","comment":{"url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/comments/77905829","id":77905829,"diff_hunk":"@@ -0,0 +1,506 @@\n+import itertools\n+import time\n+\n+import networkx as nx\n+import numpy as np\n+\n+\n+\"\"\"\n+Find the segments, lengths and tortuosity of a networkx graph by\n+        1) go through each of the disjoint graphs\n+        2) decide if it is one of the following a) line\n+        b) cycle c) acyclic tree like structure d) cyclic tree like structure\n+        e) single node\n+        3) Find all the paths in a given disjoint graph from a point whose degree is greater\n+        than 2 (branch point) to a point whose degree equal to one (end point)\n+        4) calculate distance between edges in each path and displacement to find curve length and\n+        curve displacement to find tortuosity, hausdorff dimension and contraction\n+        5) Remove all the edges in this path once they are traced\n+\"\"\"\n+\n+\n+class SegmentStats:\n+    \"\"\"\n+    Find statistics on a networkx graph of a skeleton\n+    Parameters\n+    ----------\n+    Graph : networkx graph\n+       networkx graph of a skeleton\n+\n+    Examples\n+    ------\n+           SegmentStats.countDict - A dictionary with key as the node(branch or end point)\n+                                          and number of branches connected to it\n+\n+           SegmentStats.lengthDict - A dictionary with key as the (branching index (nth branch from the start node),\n+                                           start node, end node of the branch) value = length of the branch\n+\n+           SegmentStats.tortuosityDict - A dictionary with key as the (branching index (nth branch from the start node),\n+                                             start node, end node of the branch) value = tortuosity of the branch\n+\n+           SegmentStats.totalSegments - total number of branches (segments between branch and branch points, branch and end points)\n+\n+           SegmentStats.typeGraphdict - A dictionary with the nth disjoint graph as the key and the type of graph as the value\n+\n+           SegmentStats.avgBranching - Average branching index (number of branches at a branch point) of the network\n+\n+           SegmentStats.countEndPoints- nodes with only one other node connected to them\n+\n+           SegmentStats.countBranchPoints - nodes with more than 2 nodes connected to them\n+\n+           SegmentStats.contractionDict - A dictionary with key as the (branching index (nth branch from the start node), start node,\n+                                                end node of the branch) value = contraction of the branch\n+\n+           SegmentStats.hausdorffDimensionDict - A dictionary with key as the (branching index (nth branch from the start node), start node,\n+                                                       end node of the branch) value = hausdorff dimension of the branch\n+\n+\n+    Notes\n+    --------\n+\n+    tortuosity = curveLength / curveDisplacement\n+    contraction = curveDisplacement / curveLength (better becuase there is no change of instability (undefined) in case of cycles)\n+    Hausdorff Dimension = np.log(curveLength) / np.log(curveDisplacement) https://en.wikipedia.org/wiki/Hausdorff_dimension\n+    Type of subgraphs:\n+    0 = if graph a single node\n+    1 = if graph is a single cycle\n+    2 = line (highest degree in the subgraph is 2)\n+    3 = undirected acyclic graph\n+    4 = undirected cyclic graph\n+\n+    \"\"\"\n+    def __init__(self, networkxGraph):\n+        self.networkxGraph = networkxGraph\n+        # intitialize all the instance variables of SegmentStats class\n+        self.contractionDict = {}\n+        self.countDict = {}\n+        self.cycleInfoDict = {}\n+        self.hausdorffDimensionDict = {}\n+        self.isolatedEdgeInfoDict = {}\n+        self.lengthDict = {}\n+        self.tortuosityDict = {}\n+        self.typeGraphdict = {}\n+\n+        self.cycles = 0\n+        self.edgesUntraced = 0\n+        self.totalSegments = 0\n+        self._sortedSegments = []\n+        self._visitedSources = []\n+        self._visitedPaths = []\n+        # list of _disjointGraphs\n+        self._disjointGraphs = list(nx.connected_component_subgraphs(self.networkxGraph))\n+\n+    def _getLengthAndRemoveTracedPath(self, subGraphSkeleton, path, isCycle=0, remove=1):\n+        \"\"\"\n+        Find length of a path as distance between nodes in it\n+        and Remove edges belonging to \"path\" from \"subGraphSkeleton\"\n+        Parameters\n+        ----------\n+        subGraphSkeleton : Networkx graph\n+\n+        path : list\n+           list of nodes in the path\n+\n+        isCycle : boolean\n+           Specify if path is a cycle or not\n+\n+        Returns\n+        -------\n+        subGraphSkeleton : Networkx graph\n+            graph changed inplace with visited edges removed\n+\n+        length : float\n+            Length of path\n+\n+        Notes\n+        ------\n+        given a visited path in variable path, the edges in the\n+        path are removed in the graph\n+        if isCycle = 1 , the given path belongs to a cycle,\n+        so an additional edge is formed between the last and the\n+        first node to form a closed cycle/ path and is removed\n+        and remove the edges\n+\n+        Examples\n+        --------\n+        >>> path = [(1, 2, 3), (1, 3, 3), (1, 4, 5)]\n+        >>> length = _getLengthAndRemoveTracedPath(subGraphSkeleton, path)\n+        >>> length\n+        3.2360679774997898\n+        >>> lengthCycle = _getLengthAndRemoveTracedPath(subGraphSkeleton, path, 1)\n+        6.0644951022459797\n+        \"\"\"\n+        length = 0\n+        shortestPathEdges = []\n+        if isCycle:\n+            for index, item in enumerate(path):\n+                if index + 1 < len(path):\n+                    item2 = path[index + 1]\n+                else:\n+                    item2 = path[0]\n+                if remove:\n+                    shortestPathEdges.append(tuple((item, item2)))\n+                length += np.sqrt(np.sum((np.array(item) - np.array(item2)) ** 2))\n+        else:\n+            for index, item in enumerate(path[:-1]):\n+                item2 = path[index + 1]\n+                length += np.sqrt(np.sum((np.array(item) - np.array(item2)) ** 2))\n+                if remove:\n+                    shortestPathEdges.append(tuple((item, item2)))\n+        if remove:\n+            subGraphSkeleton.remove_edges_from(shortestPathEdges)\n+        return length\n+\n+    def _checkSegmentNotTraced(self, simplePath):\n+        \"\"\"\n+        Find if simplePath is not already been visited for sorted segments of a cycle\n+\n+        Parameters\n+        ----------\n+        simplePath: list\n+           list of nodes in the path\n+\n+        Returns\n+        -------\n+        check: Boolean\n+            if simplePath is in _sortedSegments check = 0 else check = 1\n+\n+        Notes\n+        -----\n+        _sortedSegments: list of lists\n+           list of paths already traced\n+        \"\"\"\n+        check = 1\n+        for path in self._sortedSegments:\n+            if len(set(path) & set(simplePath)) > 2:\n+                check = 0\n+                break\n+        return check\n+\n+    def _singleCycle(self, subGraphSkeleton, cycle):\n+        \"\"\"\n+        Find statistics of a single cycle of a disjoint graph\n+\n+        Parameters\n+        ----------\n+        subGraphSkeleton: Networkx Graph\n+            disjoint subgraph of the skeleton's networkx graph\n+\n+        cycle: list\n+            list of nodes in the cycle\n+\n+        Returns\n+        -------\n+        subGraphSkeleton : Networkx graph\n+            graph changed inplace with visited nodes removed\n+\n+        cycleInfoDict : Dictionary\n+            class instance variable changed in place with key as nth cycle, value as list with\n+            [number of branch points on cycle, length of the cycle]\n+\n+        countDict: Dictionary\n+            class instance variable changed in place with key as source node,\n+            value is the number of segments attached to the source node\n+\n+        lengthDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the length of the segment\n+\n+        tortuosityDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the tortuosity of the segment (Nan but saved as zero)\n+\n+        contractionDictdict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the contraction of the segment (0) since it is a cycle\n+        \"\"\"\n+        sourceOnCycle = cycle[0]\n+        if sourceOnCycle not in self._visitedSources:\n+            self.countDict[sourceOnCycle] = 1\n+            self._visitedSources.append(sourceOnCycle)\n+        else:\n+            self.countDict[sourceOnCycle] += 1\n+        curveLength = self._getLengthAndRemoveTracedPath(subGraphSkeleton, cycle, 1)\n+        self.cycleInfoDict[self.cycles] = [0, curveLength]\n+        self.lengthDict[self.countDict[sourceOnCycle], sourceOnCycle, cycle[len(cycle) - 1]] = curveLength\n+        self.tortuosityDict[self.countDict[sourceOnCycle], sourceOnCycle, cycle[len(cycle) - 1]] = 0\n+        self.contractionDict[self.countDict[sourceOnCycle], sourceOnCycle, cycle[len(cycle) - 1]] = 0\n+\n+    def _cyclicTree(self, subGraphSkeleton, cycleList):\n+        \"\"\"\n+        Find statistics of a cyclic tree of a disjoint graph\n+\n+        Parameters\n+        ----------\n+        subGraphSkeleton: Networkx Graph\n+            disjoint subgraph of the skeleton's networkx graph\n+\n+        cyclesList: list of lists\n+            list of list of nodes in the cycles\n+\n+        cycles: int\n+            number of cycles in the graph so far\n+        Returns\n+        -------\n+        subGraphSkeleton : Networkx graph\n+            graph changed inplace with visited nodes removed\n+\n+        cycleInfoDict : Dictionary\n+            class instance variable changed in place with key as nth cycle, value as list with\n+            [number of branch points on cycle, length of the cycle]\n+\n+        countDict : Dictionary\n+            class instance variable changed in place with key as source node,\n+            value is the number of segments attached to the source node\n+\n+        lengthDict : Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the length of the segment\n+\n+        tortuosityDict : Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the tortuosity of the segment\n+\n+        contractionDictdict : Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the contraction of the segment\n+\n+        hausdorffDimensionDict : Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the hausdorff dimension of the segment\n+        \"\"\"\n+        for nthcycle, cycle in enumerate(cycleList):\n+            nodeDegreeDictFilt = {key: value for key, value in self._nodeDegreedict.items() if key in cycle}\n+            branchPointsOnCycle = [k for (k, v) in nodeDegreeDictFilt.items() if v != 2 and v != 1]\n+            sourceOnCycle = branchPointsOnCycle[0]\n+            if len(branchPointsOnCycle) == 1:\n+                self._singleCycle(subGraphSkeleton, cycle)\n+            else:\n+                for point in cycle:\n+                    if point in branchPointsOnCycle:\n+                        if nx.has_path(subGraphSkeleton, source=sourceOnCycle, target=point) and sourceOnCycle != point:\n+                            simplePath = nx.shortest_path(subGraphSkeleton, source=sourceOnCycle, target=point)\n+                            sortedSegment = sorted(simplePath)\n+                            if (sortedSegment not in self._sortedSegments and\n+                               sum([1 for pathPoint in simplePath if pathPoint in branchPointsOnCycle]) == 2 and\n+                               self._checkSegmentNotTraced(simplePath)):\n+                                if sourceOnCycle not in self._visitedSources:\n+                                    self.countDict[sourceOnCycle] = 1\n+                                    self._visitedSources.append(sourceOnCycle)\n+                                else:\n+                                    self.countDict[sourceOnCycle] += 1\n+                                curveLength = self._getLengthAndRemoveTracedPath(subGraphSkeleton, simplePath, isCycle=0, remove=0)\n+                                curveDisplacement = np.sqrt(np.sum((np.array(sourceOnCycle) - np.array(point)) ** 2))\n+                                self.lengthDict[self.countDict[sourceOnCycle], sourceOnCycle, point] = curveLength\n+                                self.tortuosityDict[self.countDict[sourceOnCycle], sourceOnCycle, point] = curveLength / curveDisplacement\n+                                self.contractionDict[self.countDict[sourceOnCycle], sourceOnCycle, point] = curveDisplacement / curveLength\n+                                if curveDisplacement != 0.0:\n+                                    if np.log(curveDisplacement) != 0.0:\n+                                        self.hausdorffDimensionDict[self.countDict[sourceOnCycle], sourceOnCycle, point] = np.log(curveLength) / np.log(curveDisplacement)\n+                                self._visitedPaths.append(simplePath)\n+                                self._sortedSegments.append(sortedSegment)\n+                        sourceOnCycle = point\n+            self.cycleInfoDict[self.cycles + nthcycle] = [len(branchPointsOnCycle), self._getLengthAndRemoveTracedPath(subGraphSkeleton, cycle, 1, remove=0)]\n+        for path in self._visitedPaths:\n+            self._getLengthAndRemoveTracedPath(subGraphSkeleton, simplePath, isCycle=0, remove=1)\n+        self.cycles += len(cycleList)\n+\n+    def _tree(self, subGraphSkeleton):\n+        \"\"\"\n+        Find statistics of a tree like structure of disjoint graph\n+\n+        Parameters\n+        ----------\n+        subGraphSkeleton: Networkx Graph\n+            disjoint subgraph of the skeleton's networkx graph\n+\n+        cycle: list\n+            list of nodes in the cycle\n+\n+        Returns\n+        -------\n+        subGraphSkeleton : Networkx graph\n+            graph changed inplace with visited nodes removed\n+\n+        cycleInfoDict : Dictionary\n+            class instance variable changed in place with key as nth cycle, value as list with\n+            [number of branch points on cycle, length of the cycle]\n+\n+        countDict: Dictionary\n+            class instance variable changed in place with key as source node,\n+            value is the number of segments attached to the source node\n+\n+        lengthDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the length of the segment\n+\n+        tortuosityDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the tortuosity of the segment (Nan but saved as zero)\n+\n+        contractionDictdict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the contraction of the segment (0) since it is a cycle\n+        \"\"\"\n+        listOfPerms = list(itertools.product(self._branchPoints, self._endPoints))\n+        for sourceOnTree, item in listOfPerms:\n+            if nx.has_path(subGraphSkeleton, sourceOnTree, item) and sourceOnTree != item:\n+                simplePaths = list(nx.all_simple_paths(subGraphSkeleton, source=sourceOnTree, target=item))\n+                for simplePath in simplePaths:\n+                    if sum([1 for point in simplePath if point in self._branchPoints]) == 1:\n+                        if sourceOnTree not in self._visitedSources:\n+                            self.countDict[sourceOnTree] = 1\n+                            self._visitedSources.append(sourceOnTree)\n+                        else:\n+                            self.countDict[sourceOnTree] = self.countDict[sourceOnTree] + 1\n+                        curveLength = self._getLengthAndRemoveTracedPath(subGraphSkeleton, simplePath)\n+                        curveDisplacement = np.sqrt(np.sum((np.array(sourceOnTree) - np.array(item)) ** 2))\n+                        self.lengthDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveLength\n+                        self.tortuosityDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveLength / curveDisplacement\n+                        self.contractionDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveDisplacement / curveLength\n+                        if curveDisplacement != 0.0:\n+                            if np.log(curveDisplacement) != 0.0:\n+                                self.hausdorffDimensionDict[self.countDict[sourceOnTree], sourceOnTree, item] = np.log(curveLength) / np.log(curveDisplacement)\n+\n+    def _branchToBranch(self, subGraphSkeleton):\n+        \"\"\"\n+        Find statistics of a single cycle of a disjoint graph\n+\n+        Parameters\n+        ----------\n+        subGraphSkeleton: Networkx Graph\n+            disjoint subgraph of the skeleton's networkx graph\n+\n+        cycle: list\n+            list of nodes in the cycle\n+\n+        Returns\n+        -------\n+        subGraphSkeleton : Networkx graph\n+            graph changed inplace with visited nodes removed\n+\n+        countDict: Dictionary\n+            class instance variable changed in place with key as source node,\n+            value is the number of segments attached to the source node\n+\n+        lengthDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the length of the segment\n+\n+        tortuosityDict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the tortuosity of the segment (Nan but saved as zero)\n+\n+        contractionDictdict: Dictionary\n+            class instance variable changed in place with key as index of the segment from the source node,\n+            source node, target node, value is the contraction of the segment (0) since it is a cycle\n+\n+        \"\"\"\n+        listOfPerms = list(itertools.permutations(self._branchPoints, 2))\n+        for sourceOnTree, item in listOfPerms:\n+            if nx.has_path(subGraphSkeleton, sourceOnTree, item) and sourceOnTree != item:\n+                simplePaths = list(nx.all_simple_paths(subGraphSkeleton, source=sourceOnTree, target=item))\n+                for simplePath in simplePaths:\n+                    simplePath\n+                    if sum([1 for point in simplePath if point in self._branchPoints]) == 2:\n+                        if sourceOnTree not in self._visitedSources:\n+                            self.countDict[sourceOnTree] = 1\n+                            self._visitedSources.append(sourceOnTree)\n+                        else:\n+                            self.countDict[sourceOnTree] = self.countDict[sourceOnTree] + 1\n+                        curveLength = self._getLengthAndRemoveTracedPath(subGraphSkeleton, simplePath)\n+                        curveDisplacement = np.sqrt(np.sum((np.array(sourceOnTree) - np.array(item)) ** 2))\n+                        self.lengthDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveLength\n+                        self.tortuosityDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveLength / curveDisplacement\n+                        self.contractionDict[self.countDict[sourceOnTree], sourceOnTree, item] = curveDisplacement / curveLength\n+                        if curveDisplacement != 0.0:\n+                            if np.log(curveDisplacement) != 0.0:\n+                                self.hausdorffDimensionDict[self.countDict[sourceOnTree], sourceOnTree, item] = np.log(curveLength) / np.log(curveDisplacement)\n+\n+    def setStats(self):","path":"metrics/segmentStats.py","position":420,"original_position":420,"commit_id":"b68c0429edcaf5c483ad1e214c7c80c3228a4d48","original_commit_id":"b68c0429edcaf5c483ad1e214c7c80c3228a4d48","user":{"login":"belisarius222","id":874741,"avatar_url":"https://avatars.githubusercontent.com/u/874741?v=3","gravatar_id":"","url":"https://api.github.com/users/belisarius222","html_url":"https://github.com/belisarius222","followers_url":"https://api.github.com/users/belisarius222/followers","following_url":"https://api.github.com/users/belisarius222/following{/other_user}","gists_url":"https://api.github.com/users/belisarius222/gists{/gist_id}","starred_url":"https://api.github.com/users/belisarius222/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/belisarius222/subscriptions","organizations_url":"https://api.github.com/users/belisarius222/orgs","repos_url":"https://api.github.com/users/belisarius222/repos","events_url":"https://api.github.com/users/belisarius222/events{/privacy}","received_events_url":"https://api.github.com/users/belisarius222/received_events","type":"User","site_admin":false},"body":"This method is impenetrable to a mere human mind such as my own. I get the feeling this is the main method that calls the other ones, but I'm not entirely sure.\r\n\r\nI suggest:\r\na) Document what this method does, including each of the overall steps it takes. Of any of the methods in the class to document, this one might actually be the most important.\r\nb) Split this up into smaller functions. \r\n\r\nIdeally, each method should operate at a single level of abstraction. That means that some functions (probably including this one) would only orchestrate calls to other methods without delving into the math themselves, while other functions would do the lower-level dirty work of manipulating sets and arrays and doing intricate numpy calls. That way, the orchestrating method can be the main point where people start to read the code, much like an abstract in a scientific paper. It should generally be one of the first methods defined, so that reading the code feels like reading an essay, with the first paragraph describing the structure of the rest of the document.","created_at":"2016-09-07T21:18:15Z","updated_at":"2016-09-07T21:18:15Z","html_url":"https://github.com/3Scan/3scan-skeleton/pull/1#discussion_r77905829","pull_request_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/comments/77905829"},"html":{"href":"https://github.com/3Scan/3scan-skeleton/pull/1#discussion_r77905829"},"pull_request":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1","id":84202694,"html_url":"https://github.com/3Scan/3scan-skeleton/pull/1","diff_url":"https://github.com/3Scan/3scan-skeleton/pull/1.diff","patch_url":"https://github.com/3Scan/3scan-skeleton/pull/1.patch","issue_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/1","number":1,"state":"open","locked":false,"title":"Cython","user":{"login":"pranathivemuri","id":10284094,"avatar_url":"https://avatars.githubusercontent.com/u/10284094?v=3","gravatar_id":"","url":"https://api.github.com/users/pranathivemuri","html_url":"https://github.com/pranathivemuri","followers_url":"https://api.github.com/users/pranathivemuri/followers","following_url":"https://api.github.com/users/pranathivemuri/following{/other_user}","gists_url":"https://api.github.com/users/pranathivemuri/gists{/gist_id}","starred_url":"https://api.github.com/users/pranathivemuri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pranathivemuri/subscriptions","organizations_url":"https://api.github.com/users/pranathivemuri/orgs","repos_url":"https://api.github.com/users/pranathivemuri/repos","events_url":"https://api.github.com/users/pranathivemuri/events{/privacy}","received_events_url":"https://api.github.com/users/pranathivemuri/received_events","type":"User","site_admin":false},"body":"@belisarius222: This is the refactored code I was talking about on Friday. Can you please review the code?","created_at":"2016-09-06T21:49:51Z","updated_at":"2016-09-07T21:18:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"da397eb4e3bfd29c618508e045292139dda9fe69","assignee":{"login":"mpesavento","id":154588,"avatar_url":"https://avatars.githubusercontent.com/u/154588?v=3","gravatar_id":"","url":"https://api.github.com/users/mpesavento","html_url":"https://github.com/mpesavento","followers_url":"https://api.github.com/users/mpesavento/followers","following_url":"https://api.github.com/users/mpesavento/following{/other_user}","gists_url":"https://api.github.com/users/mpesavento/gists{/gist_id}","starred_url":"https://api.github.com/users/mpesavento/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mpesavento/subscriptions","organizations_url":"https://api.github.com/users/mpesavento/orgs","repos_url":"https://api.github.com/users/mpesavento/repos","events_url":"https://api.github.com/users/mpesavento/events{/privacy}","received_events_url":"https://api.github.com/users/mpesavento/received_events","type":"User","site_admin":false},"assignees":[{"login":"mpesavento","id":154588,"avatar_url":"https://avatars.githubusercontent.com/u/154588?v=3","gravatar_id":"","url":"https://api.github.com/users/mpesavento","html_url":"https://github.com/mpesavento","followers_url":"https://api.github.com/users/mpesavento/followers","following_url":"https://api.github.com/users/mpesavento/following{/other_user}","gists_url":"https://api.github.com/users/mpesavento/gists{/gist_id}","starred_url":"https://api.github.com/users/mpesavento/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mpesavento/subscriptions","organizations_url":"https://api.github.com/users/mpesavento/orgs","repos_url":"https://api.github.com/users/mpesavento/repos","events_url":"https://api.github.com/users/mpesavento/events{/privacy}","received_events_url":"https://api.github.com/users/mpesavento/received_events","type":"User","site_admin":false},{"login":"meawoppl","id":579782,"avatar_url":"https://avatars.githubusercontent.com/u/579782?v=3","gravatar_id":"","url":"https://api.github.com/users/meawoppl","html_url":"https://github.com/meawoppl","followers_url":"https://api.github.com/users/meawoppl/followers","following_url":"https://api.github.com/users/meawoppl/following{/other_user}","gists_url":"https://api.github.com/users/meawoppl/gists{/gist_id}","starred_url":"https://api.github.com/users/meawoppl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meawoppl/subscriptions","organizations_url":"https://api.github.com/users/meawoppl/orgs","repos_url":"https://api.github.com/users/meawoppl/repos","events_url":"https://api.github.com/users/meawoppl/events{/privacy}","received_events_url":"https://api.github.com/users/meawoppl/received_events","type":"User","site_admin":false},{"login":"belisarius222","id":874741,"avatar_url":"https://avatars.githubusercontent.com/u/874741?v=3","gravatar_id":"","url":"https://api.github.com/users/belisarius222","html_url":"https://github.com/belisarius222","followers_url":"https://api.github.com/users/belisarius222/followers","following_url":"https://api.github.com/users/belisarius222/following{/other_user}","gists_url":"https://api.github.com/users/belisarius222/gists{/gist_id}","starred_url":"https://api.github.com/users/belisarius222/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/belisarius222/subscriptions","organizations_url":"https://api.github.com/users/belisarius222/orgs","repos_url":"https://api.github.com/users/belisarius222/repos","events_url":"https://api.github.com/users/belisarius222/events{/privacy}","received_events_url":"https://api.github.com/users/belisarius222/received_events","type":"User","site_admin":false},{"login":"pranathivemuri","id":10284094,"avatar_url":"https://avatars.githubusercontent.com/u/10284094?v=3","gravatar_id":"","url":"https://api.github.com/users/pranathivemuri","html_url":"https://github.com/pranathivemuri","followers_url":"https://api.github.com/users/pranathivemuri/followers","following_url":"https://api.github.com/users/pranathivemuri/following{/other_user}","gists_url":"https://api.github.com/users/pranathivemuri/gists{/gist_id}","starred_url":"https://api.github.com/users/pranathivemuri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pranathivemuri/subscriptions","organizations_url":"https://api.github.com/users/pranathivemuri/orgs","repos_url":"https://api.github.com/users/pranathivemuri/repos","events_url":"https://api.github.com/users/pranathivemuri/events{/privacy}","received_events_url":"https://api.github.com/users/pranathivemuri/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1/commits","review_comments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1/comments","review_comment_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/comments{/number}","comments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/1/comments","statuses_url":"https://api.github.com/repos/3Scan/3scan-skeleton/statuses/b68c0429edcaf5c483ad1e214c7c80c3228a4d48","head":{"label":"3Scan:cython","ref":"cython","sha":"b68c0429edcaf5c483ad1e214c7c80c3228a4d48","user":{"login":"3Scan","id":1224334,"avatar_url":"https://avatars.githubusercontent.com/u/1224334?v=3","gravatar_id":"","url":"https://api.github.com/users/3Scan","html_url":"https://github.com/3Scan","followers_url":"https://api.github.com/users/3Scan/followers","following_url":"https://api.github.com/users/3Scan/following{/other_user}","gists_url":"https://api.github.com/users/3Scan/gists{/gist_id}","starred_url":"https://api.github.com/users/3Scan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/3Scan/subscriptions","organizations_url":"https://api.github.com/users/3Scan/orgs","repos_url":"https://api.github.com/users/3Scan/repos","events_url":"https://api.github.com/users/3Scan/events{/privacy}","received_events_url":"https://api.github.com/users/3Scan/received_events","type":"Organization","site_admin":false},"repo":{"id":46076331,"name":"3scan-skeleton","full_name":"3Scan/3scan-skeleton","owner":{"login":"3Scan","id":1224334,"avatar_url":"https://avatars.githubusercontent.com/u/1224334?v=3","gravatar_id":"","url":"https://api.github.com/users/3Scan","html_url":"https://github.com/3Scan","followers_url":"https://api.github.com/users/3Scan/followers","following_url":"https://api.github.com/users/3Scan/following{/other_user}","gists_url":"https://api.github.com/users/3Scan/gists{/gist_id}","starred_url":"https://api.github.com/users/3Scan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/3Scan/subscriptions","organizations_url":"https://api.github.com/users/3Scan/orgs","repos_url":"https://api.github.com/users/3Scan/repos","events_url":"https://api.github.com/users/3Scan/events{/privacy}","received_events_url":"https://api.github.com/users/3Scan/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/3Scan/3scan-skeleton","description":"3D Image Skeletonization Tools","fork":false,"url":"https://api.github.com/repos/3Scan/3scan-skeleton","forks_url":"https://api.github.com/repos/3Scan/3scan-skeleton/forks","keys_url":"https://api.github.com/repos/3Scan/3scan-skeleton/keys{/key_id}","collaborators_url":"https://api.github.com/repos/3Scan/3scan-skeleton/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/3Scan/3scan-skeleton/teams","hooks_url":"https://api.github.com/repos/3Scan/3scan-skeleton/hooks","issue_events_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/events{/number}","events_url":"https://api.github.com/repos/3Scan/3scan-skeleton/events","assignees_url":"https://api.github.com/repos/3Scan/3scan-skeleton/assignees{/user}","branches_url":"https://api.github.com/repos/3Scan/3scan-skeleton/branches{/branch}","tags_url":"https://api.github.com/repos/3Scan/3scan-skeleton/tags","blobs_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/refs{/sha}","trees_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/trees{/sha}","statuses_url":"https://api.github.com/repos/3Scan/3scan-skeleton/statuses/{sha}","languages_url":"https://api.github.com/repos/3Scan/3scan-skeleton/languages","stargazers_url":"https://api.github.com/repos/3Scan/3scan-skeleton/stargazers","contributors_url":"https://api.github.com/repos/3Scan/3scan-skeleton/contributors","subscribers_url":"https://api.github.com/repos/3Scan/3scan-skeleton/subscribers","subscription_url":"https://api.github.com/repos/3Scan/3scan-skeleton/subscription","commits_url":"https://api.github.com/repos/3Scan/3scan-skeleton/commits{/sha}","git_commits_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/commits{/sha}","comments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/comments{/number}","issue_comment_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/comments{/number}","contents_url":"https://api.github.com/repos/3Scan/3scan-skeleton/contents/{+path}","compare_url":"https://api.github.com/repos/3Scan/3scan-skeleton/compare/{base}...{head}","merges_url":"https://api.github.com/repos/3Scan/3scan-skeleton/merges","archive_url":"https://api.github.com/repos/3Scan/3scan-skeleton/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/3Scan/3scan-skeleton/downloads","issues_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues{/number}","pulls_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls{/number}","milestones_url":"https://api.github.com/repos/3Scan/3scan-skeleton/milestones{/number}","notifications_url":"https://api.github.com/repos/3Scan/3scan-skeleton/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/3Scan/3scan-skeleton/labels{/name}","releases_url":"https://api.github.com/repos/3Scan/3scan-skeleton/releases{/id}","deployments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/deployments","created_at":"2015-11-12T19:38:39Z","updated_at":"2016-01-11T18:41:55Z","pushed_at":"2016-09-07T20:10:59Z","git_url":"git://github.com/3Scan/3scan-skeleton.git","ssh_url":"git@github.com:3Scan/3scan-skeleton.git","clone_url":"https://github.com/3Scan/3scan-skeleton.git","svn_url":"https://github.com/3Scan/3scan-skeleton","homepage":null,"size":1487,"stargazers_count":0,"watchers_count":0,"language":"Jupyter Notebook","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"3Scan:master","ref":"master","sha":"88b293f6a2b5ab5fdd1345444d122b0bef201934","user":{"login":"3Scan","id":1224334,"avatar_url":"https://avatars.githubusercontent.com/u/1224334?v=3","gravatar_id":"","url":"https://api.github.com/users/3Scan","html_url":"https://github.com/3Scan","followers_url":"https://api.github.com/users/3Scan/followers","following_url":"https://api.github.com/users/3Scan/following{/other_user}","gists_url":"https://api.github.com/users/3Scan/gists{/gist_id}","starred_url":"https://api.github.com/users/3Scan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/3Scan/subscriptions","organizations_url":"https://api.github.com/users/3Scan/orgs","repos_url":"https://api.github.com/users/3Scan/repos","events_url":"https://api.github.com/users/3Scan/events{/privacy}","received_events_url":"https://api.github.com/users/3Scan/received_events","type":"Organization","site_admin":false},"repo":{"id":46076331,"name":"3scan-skeleton","full_name":"3Scan/3scan-skeleton","owner":{"login":"3Scan","id":1224334,"avatar_url":"https://avatars.githubusercontent.com/u/1224334?v=3","gravatar_id":"","url":"https://api.github.com/users/3Scan","html_url":"https://github.com/3Scan","followers_url":"https://api.github.com/users/3Scan/followers","following_url":"https://api.github.com/users/3Scan/following{/other_user}","gists_url":"https://api.github.com/users/3Scan/gists{/gist_id}","starred_url":"https://api.github.com/users/3Scan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/3Scan/subscriptions","organizations_url":"https://api.github.com/users/3Scan/orgs","repos_url":"https://api.github.com/users/3Scan/repos","events_url":"https://api.github.com/users/3Scan/events{/privacy}","received_events_url":"https://api.github.com/users/3Scan/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/3Scan/3scan-skeleton","description":"3D Image Skeletonization Tools","fork":false,"url":"https://api.github.com/repos/3Scan/3scan-skeleton","forks_url":"https://api.github.com/repos/3Scan/3scan-skeleton/forks","keys_url":"https://api.github.com/repos/3Scan/3scan-skeleton/keys{/key_id}","collaborators_url":"https://api.github.com/repos/3Scan/3scan-skeleton/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/3Scan/3scan-skeleton/teams","hooks_url":"https://api.github.com/repos/3Scan/3scan-skeleton/hooks","issue_events_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/events{/number}","events_url":"https://api.github.com/repos/3Scan/3scan-skeleton/events","assignees_url":"https://api.github.com/repos/3Scan/3scan-skeleton/assignees{/user}","branches_url":"https://api.github.com/repos/3Scan/3scan-skeleton/branches{/branch}","tags_url":"https://api.github.com/repos/3Scan/3scan-skeleton/tags","blobs_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/refs{/sha}","trees_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/trees{/sha}","statuses_url":"https://api.github.com/repos/3Scan/3scan-skeleton/statuses/{sha}","languages_url":"https://api.github.com/repos/3Scan/3scan-skeleton/languages","stargazers_url":"https://api.github.com/repos/3Scan/3scan-skeleton/stargazers","contributors_url":"https://api.github.com/repos/3Scan/3scan-skeleton/contributors","subscribers_url":"https://api.github.com/repos/3Scan/3scan-skeleton/subscribers","subscription_url":"https://api.github.com/repos/3Scan/3scan-skeleton/subscription","commits_url":"https://api.github.com/repos/3Scan/3scan-skeleton/commits{/sha}","git_commits_url":"https://api.github.com/repos/3Scan/3scan-skeleton/git/commits{/sha}","comments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/comments{/number}","issue_comment_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/comments{/number}","contents_url":"https://api.github.com/repos/3Scan/3scan-skeleton/contents/{+path}","compare_url":"https://api.github.com/repos/3Scan/3scan-skeleton/compare/{base}...{head}","merges_url":"https://api.github.com/repos/3Scan/3scan-skeleton/merges","archive_url":"https://api.github.com/repos/3Scan/3scan-skeleton/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/3Scan/3scan-skeleton/downloads","issues_url":"https://api.github.com/repos/3Scan/3scan-skeleton/issues{/number}","pulls_url":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls{/number}","milestones_url":"https://api.github.com/repos/3Scan/3scan-skeleton/milestones{/number}","notifications_url":"https://api.github.com/repos/3Scan/3scan-skeleton/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/3Scan/3scan-skeleton/labels{/name}","releases_url":"https://api.github.com/repos/3Scan/3scan-skeleton/releases{/id}","deployments_url":"https://api.github.com/repos/3Scan/3scan-skeleton/deployments","created_at":"2015-11-12T19:38:39Z","updated_at":"2016-01-11T18:41:55Z","pushed_at":"2016-09-07T20:10:59Z","git_url":"git://github.com/3Scan/3scan-skeleton.git","ssh_url":"git@github.com:3Scan/3scan-skeleton.git","clone_url":"https://github.com/3Scan/3scan-skeleton.git","svn_url":"https://github.com/3Scan/3scan-skeleton","homepage":null,"size":1487,"stargazers_count":0,"watchers_count":0,"language":"Jupyter Notebook","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1"},"html":{"href":"https://github.com/3Scan/3scan-skeleton/pull/1"},"issue":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/1"},"comments":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/3Scan/3scan-skeleton/statuses/b68c0429edcaf5c483ad1e214c7c80c3228a4d48"}}}}
{"actor":{"display_login":"belisarius222"}}