Repository: LLNL/hatchet

Issue:
Update the Query Language High-Level API to Allow for Filtering with non-DataFrame Data
Currently, the filter field (Python dict) for a query node in the high-level query language API must be keyed on a column of the `pandas.DataFrame` stored within the `GraphFrame`. In the future, these filters should be allowed to be keyed on other node data not stored in the DataFrame, like the node's `_depth` and `_hatchet_nid` fields.

Discussion:
ilumsden: While testing this PR, I found a small "bug" that occasionally causes multiple copies of the same matched path to be returned by `QueryMatcher.apply`. This bug would never have caused an issue with the results of the query language, so I'm just going to bundle the fix in with this PR.
ilumsden: The additional unit tests for GraphFrames with index levels have been added.

@slabasan @bhatele this PR is now ready for review. I might still have to handle some formatting stuff, but otherwise this PR is ready to go.

Patch:
diff --git a/docs/examples/read/dag_literal.py b/docs/examples/read/dag_literal.py
index 38af499..1b6e31f 100755
--- a/docs/examples/read/dag_literal.py
+++ b/docs/examples/read/dag_literal.py
@@ -10,36 +10,44 @@ if __name__ == "__main__":
         [
             {
                 "name": "foo",
+                "type": "function",
                 "metrics": {"time (inc)": 130.0, "time": 0.0},
                 "children": [
                     {
                         "name": "bar",
+                        "type": "function",
                         "metrics": {"time (inc)": 20.0, "time": 5.0},
                         "children": [
                             {
                                 "name": "baz",
+                                "type": "function",
                                 "metrics": {"time (inc)": 5.0, "time": 5.0},
                             },
                             {
                                 "name": "grault",
+                                "type": "function",
                                 "metrics": {"time (inc)": 10.0, "time": 10.0},
                             },
                         ],
                     },
                     {
                         "name": "qux",
+                        "type": "function",
                         "metrics": {"time (inc)": 60.0, "time": 0.0},
                         "children": [
                             {
                                 "name": "quux",
+                                "type": "function",
                                 "metrics": {"time (inc)": 60.0, "time": 5.0},
                                 "children": [
                                     {
                                         "name": "corge",
+                                        "type": "function",
                                         "metrics": {"time (inc)": 55.0, "time": 10.0},
                                         "children": [
                                             {
                                                 "name": "bar",
+                                                "type": "function",
                                                 "metrics": {
                                                     "time (inc)": 20.0,
                                                     "time": 5.0,
@@ -47,6 +55,7 @@ if __name__ == "__main__":
                                                 "children": [
                                                     {
                                                         "name": "baz",
+                                                        "type": "function",
                                                         "metrics": {
                                                             "time (inc)": 5.0,
                                                             "time": 5.0,
@@ -54,6 +63,7 @@ if __name__ == "__main__":
                                                     },
                                                     {
                                                         "name": "grault",
+                                                        "type": "function",
                                                         "metrics": {
                                                             "time (inc)": 10.0,
                                                             "time": 10.0,
@@ -63,6 +73,7 @@ if __name__ == "__main__":
                                             },
                                             {
                                                 "name": "grault",
+                                                "type": "function",
                                                 "metrics": {
                                                     "time (inc)": 10.0,
                                                     "time": 10.0,
@@ -70,6 +81,7 @@ if __name__ == "__main__":
                                             },
                                             {
                                                 "name": "garply",
+                                                "type": "function",
                                                 "metrics": {
                                                     "time (inc)": 15.0,
                                                     "time": 15.0,
@@ -83,22 +95,27 @@ if __name__ == "__main__":
                     },
                     {
                         "name": "waldo",
+                        "type": "function",
                         "metrics": {"time (inc)": 50.0, "time": 0.0},
                         "children": [
                             {
                                 "name": "fred",
+                                "type": "function",
                                 "metrics": {"time (inc)": 35.0, "time": 5.0},
                                 "children": [
                                     {
                                         "name": "plugh",
+                                        "type": "function",
                                         "metrics": {"time (inc)": 5.0, "time": 5.0},
                                     },
                                     {
                                         "name": "xyzzy",
+                                        "type": "function",
                                         "metrics": {"time (inc)": 25.0, "time": 5.0},
                                         "children": [
                                             {
                                                 "name": "thud",
+                                                "type": "function",
                                                 "metrics": {
                                                     "time (inc)": 25.0,
                                                     "time": 5.0,
@@ -106,6 +123,7 @@ if __name__ == "__main__":
                                                 "children": [
                                                     {
                                                         "name": "baz",
+                                                        "type": "function",
                                                         "metrics": {
                                                             "time (inc)": 5.0,
                                                             "time": 5.0,
@@ -113,6 +131,7 @@ if __name__ == "__main__":
                                                     },
                                                     {
                                                         "name": "garply",
+                                                        "type": "function",
                                                         "metrics": {
                                                             "time (inc)": 15.0,
                                                             "time": 15.0,
@@ -126,6 +145,7 @@ if __name__ == "__main__":
                             },
                             {
                                 "name": "garply",
+                                "type": "function",
                                 "metrics": {"time (inc)": 15.0, "time": 15.0},
                             },
                         ],
@@ -134,24 +154,29 @@ if __name__ == "__main__":
             },
             {
                 "name": "ほげ (hoge)",
+                "type": "function",
                 "metrics": {"time (inc)": 30.0, "time": 0.0},
                 "children": [
                     {
                         "name": "(ぴよ (piyo)",
+                        "type": "function",
                         "metrics": {"time (inc)": 15.0, "time": 5.0},
                         "children": [
                             {
                                 "name": "ふが (fuga)",
+                                "type": "function",
                                 "metrics": {"time (inc)": 5.0, "time": 5.0},
                             },
                             {
                                 "name": "ほげら (hogera)",
+                                "type": "function",
                                 "metrics": {"time (inc)": 5.0, "time": 5.0},
                             },
                         ],
                     },
                     {
                         "name": "ほげほげ (hogehoge)",
+                        "type": "function",
                         "metrics": {"time (inc)": 15.0, "time": 15.0},
                     },
                 ],
diff --git a/docs/examples/tutorial/hatchet_query_examples.ipynb b/docs/examples/tutorial/hatchet_query_examples.ipynb
index a0c0850..e0705fe 100644
--- a/docs/examples/tutorial/hatchet_query_examples.ipynb
+++ b/docs/examples/tutorial/hatchet_query_examples.ipynb
@@ -39,33 +39,44 @@
     "    graph_dict = [\n",
     "        {\n",
     "            \"name\": \"foo\",\n",
+    "            \"type\": \"function\",\n",
     "            \"metrics\": {\"time (inc)\": 130.0, \"time\": 0.0},\n",
     "            \"children\": [\n",
     "                {\n",
     "                    \"name\": \"bar\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 20.0, \"time\": 5.0},\n",
     "                    \"children\": [\n",
-    "                        {\"name\": \"baz\", \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0}},\n",
+    "                        {\n",
+    "                            \"name\": \"baz\",\n",
+    "                            \"type\": \"function\",\n",
+    "                            \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0}\n",
+    "                        },\n",
     "                        {\n",
     "                            \"name\": \"grault\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 10.0, \"time\": 10.0},\n",
     "                        },\n",
     "                    ],\n",
     "                },\n",
     "                {\n",
     "                    \"name\": \"qux\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 60.0, \"time\": 0.0},\n",
     "                    \"children\": [\n",
     "                        {\n",
     "                            \"name\": \"quux\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 60.0, \"time\": 5.0},\n",
     "                            \"children\": [\n",
     "                                {\n",
     "                                    \"name\": \"corge\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\"time (inc)\": 55.0, \"time\": 10.0},\n",
     "                                    \"children\": [\n",
     "                                        {\n",
     "                                            \"name\": \"bar\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 20.0,\n",
     "                                                \"time\": 5.0,\n",
@@ -73,6 +84,7 @@
     "                                            \"children\": [\n",
     "                                                {\n",
     "                                                    \"name\": \"baz\",\n",
+    "                                                    \"type\": \"function\",\n",
     "                                                    \"metrics\": {\n",
     "                                                        \"time (inc)\": 5.0,\n",
     "                                                        \"time\": 5.0,\n",
@@ -80,6 +92,7 @@
     "                                                },\n",
     "                                                {\n",
     "                                                    \"name\": \"grault\",\n",
+    "                                                    \"type\": \"function\",\n",
     "                                                    \"metrics\": {\n",
     "                                                        \"time (inc)\": 10.0,\n",
     "                                                        \"time\": 10.0,\n",
@@ -89,6 +102,7 @@
     "                                        },\n",
     "                                        {\n",
     "                                            \"name\": \"grault\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 10.0,\n",
     "                                                \"time\": 10.0,\n",
@@ -96,6 +110,7 @@
     "                                        },\n",
     "                                        {\n",
     "                                            \"name\": \"garply\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 15.0,\n",
     "                                                \"time\": 15.0,\n",
@@ -109,22 +124,27 @@
     "                },\n",
     "                {\n",
     "                    \"name\": \"waldo\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 50.0, \"time\": 0.0},\n",
     "                    \"children\": [\n",
     "                        {\n",
     "                            \"name\": \"fred\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 35.0, \"time\": 5.0},\n",
     "                            \"children\": [\n",
     "                                {\n",
     "                                    \"name\": \"plugh\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                                },\n",
     "                                {\n",
     "                                    \"name\": \"xyzzy\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\"time (inc)\": 25.0, \"time\": 5.0},\n",
     "                                    \"children\": [\n",
     "                                        {\n",
     "                                            \"name\": \"thud\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 25.0,\n",
     "                                                \"time\": 5.0,\n",
@@ -132,6 +152,7 @@
     "                                            \"children\": [\n",
     "                                                {\n",
     "                                                    \"name\": \"baz\",\n",
+    "                                                    \"type\": \"function\",\n",
     "                                                    \"metrics\": {\n",
     "                                                        \"time (inc)\": 5.0,\n",
     "                                                        \"time\": 5.0,\n",
@@ -139,6 +160,7 @@
     "                                                },\n",
     "                                                {\n",
     "                                                    \"name\": \"garply\",\n",
+    "                                                    \"type\": \"function\",\n",
     "                                                    \"metrics\": {\n",
     "                                                        \"time (inc)\": 15.0,\n",
     "                                                        \"time\": 15.0,\n",
@@ -152,6 +174,7 @@
     "                        },\n",
     "                        {\n",
     "                            \"name\": \"garply\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 15.0, \"time\": 15.0},\n",
     "                        },\n",
     "                    ],\n",
@@ -160,15 +183,22 @@
     "        },\n",
     "        {\n",
     "            \"name\": \"waldo\",\n",
+    "            \"type\": \"function\",\n",
     "            \"metrics\": {\"time (inc)\": 30.0, \"time\": 10.0},\n",
     "            \"children\": [\n",
     "                {\n",
     "                    \"name\": \"bar\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 20.0, \"time\": 5.0},\n",
     "                    \"children\": [\n",
-    "                        {\"name\": \"baz\", \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0}},\n",
+    "                        {\n",
+    "                            \"name\": \"baz\",\n",
+    "                            \"type\": \"function\",\n",
+    "                            \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0}\n",
+    "                        },\n",
     "                        {\n",
     "                            \"name\": \"grault\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 10.0, \"time\": 10.0},\n",
     "                        },\n",
     "                    ],\n",
diff --git a/docs/examples/tutorial/roundtrip-demo.ipynb b/docs/examples/tutorial/roundtrip-demo.ipynb
index 2eb2b49..b95e837 100644
--- a/docs/examples/tutorial/roundtrip-demo.ipynb
+++ b/docs/examples/tutorial/roundtrip-demo.ipynb
@@ -56,36 +56,44 @@
     "literal_tree = [\n",
     "{\n",
     "    \"name\": \"foo\",\n",
+    "    \"type\": \"function\",\n",
     "    \"metrics\": {\"time (inc)\": 130.0, \"time\": 0.0},\n",
     "    \"children\": [\n",
     "        {\n",
     "            \"name\": \"bar\",\n",
+    "            \"type\": \"function\",\n",
     "            \"metrics\": {\"time (inc)\": 20.0, \"time\": 5.0},\n",
     "            \"children\": [\n",
     "                {\n",
     "                    \"name\": \"baz\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                },\n",
     "                {\n",
     "                    \"name\": \"grault\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 10.0, \"time\": 10.0},\n",
     "                },\n",
     "            ],\n",
     "        },\n",
     "        {\n",
     "            \"name\": \"qux\",\n",
+    "            \"type\": \"function\",\n",
     "            \"metrics\": {\"time (inc)\": 60.0, \"time\": 0.0},\n",
     "            \"children\": [\n",
     "                {\n",
     "                    \"name\": \"quux\",\n",
+    "                    \"type\": \"function\",\n",
     "                    \"metrics\": {\"time (inc)\": 60.0, \"time\": 5.0},\n",
     "                    \"children\": [\n",
     "                        {\n",
     "                            \"name\": \"corge\",\n",
+    "                            \"type\": \"function\",\n",
     "                            \"metrics\": {\"time (inc)\": 55.0, \"time\": 10.0},\n",
     "                            \"children\": [\n",
     "                                {\n",
     "                                    \"name\": \"bar\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\n",
     "                                        \"time (inc)\": 20.0,\n",
     "                                        \"time\": 5.0,\n",
@@ -93,6 +101,7 @@
     "                                    \"children\": [\n",
     "                                        {\n",
     "                                            \"name\": \"baz\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 5.0,\n",
     "                                                \"time\": 5.0,\n",
@@ -100,6 +109,7 @@
     "                                        },\n",
     "                                        {\n",
     "                                            \"name\": \"grault\",\n",
+    "                                            \"type\": \"function\",\n",
     "                                            \"metrics\": {\n",
     "                                                \"time (inc)\": 10.0,\n",
     "                                                \"time\": 10.0,\n",
@@ -109,6 +119,7 @@
     "                                },\n",
     "                                {\n",
     "                                    \"name\": \"grault\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\n",
     "                                        \"time (inc)\": 10.0,\n",
     "                                        \"time\": 10.0,\n",
@@ -116,6 +127,7 @@
     "                                },\n",
     "                                {\n",
     "                                    \"name\": \"garply\",\n",
+    "                                    \"type\": \"function\",\n",
     "                                    \"metrics\": {\n",
     "                                        \"time (inc)\": 15.0,\n",
     "                                        \"time\": 15.0,\n",
@@ -235,36 +247,44 @@
     "multiple_roots = [\n",
     "    {\n",
     "        \"name\": \"foo\",\n",
+    "        \"type\": \"function\",\n",
     "        \"metrics\": {\"time (inc)\": 130.0, \"time\": 0.0},\n",
     "        \"children\": [\n",
     "            {\n",
     "                \"name\": \"bar\",\n",
+    "                \"type\": \"function\",\n",
     "                \"metrics\": {\"time (inc)\": 20.0, \"time\": 5.0},\n",
     "                \"children\": [\n",
     "                    {\n",
     "                        \"name\": \"baz\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                    },\n",
     "                    {\n",
     "                        \"name\": \"grault\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 10.0, \"time\": 10.0},\n",
     "                    },\n",
     "                ],\n",
     "            },\n",
     "            {\n",
     "                \"name\": \"qux\",\n",
+    "                \"type\": \"function\",\n",
     "                \"metrics\": {\"time (inc)\": 60.0, \"time\": 0.0},\n",
     "                \"children\": [\n",
     "                    {\n",
     "                        \"name\": \"quux\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 60.0, \"time\": 5.0},\n",
     "                        \"children\": [\n",
     "                            {\n",
     "                                \"name\": \"corge\",\n",
+    "                                \"type\": \"function\",\n",
     "                                \"metrics\": {\"time (inc)\": 55.0, \"time\": 10.0},\n",
     "                                \"children\": [\n",
     "                                    {\n",
     "                                        \"name\": \"bar\",\n",
+    "                                        \"type\": \"function\",\n",
     "                                        \"metrics\": {\n",
     "                                            \"time (inc)\": 20.0,\n",
     "                                            \"time\": 5.0,\n",
@@ -272,6 +292,7 @@
     "                                        \"children\": [\n",
     "                                            {\n",
     "                                                \"name\": \"baz\",\n",
+    "                                                \"type\": \"function\",\n",
     "                                                \"metrics\": {\n",
     "                                                    \"time (inc)\": 5.0,\n",
     "                                                    \"time\": 5.0,\n",
@@ -279,6 +300,7 @@
     "                                            },\n",
     "                                            {\n",
     "                                                \"name\": \"grault\",\n",
+    "                                                \"type\": \"function\",\n",
     "                                                \"metrics\": {\n",
     "                                                    \"time (inc)\": 10.0,\n",
     "                                                    \"time\": 10.0,\n",
@@ -288,6 +310,7 @@
     "                                    },\n",
     "                                    {\n",
     "                                        \"name\": \"grault\",\n",
+    "                                        \"type\": \"function\",\n",
     "                                        \"metrics\": {\n",
     "                                            \"time (inc)\": 10.0,\n",
     "                                            \"time\": 10.0,\n",
@@ -295,6 +318,7 @@
     "                                    },\n",
     "                                    {\n",
     "                                        \"name\": \"garply\",\n",
+    "                                        \"type\": \"function\",\n",
     "                                        \"metrics\": {\n",
     "                                            \"time (inc)\": 15.0,\n",
     "                                            \"time\": 15.0,\n",
@@ -308,22 +332,27 @@
     "            },\n",
     "            {\n",
     "                \"name\": \"waldo\",\n",
+    "                \"type\": \"function\",\n",
     "                \"metrics\": {\"time (inc)\": 50.0, \"time\": 0.0},\n",
     "                \"children\": [\n",
     "                    {\n",
     "                        \"name\": \"fred\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 35.0, \"time\": 5.0},\n",
     "                        \"children\": [\n",
     "                            {\n",
     "                                \"name\": \"plugh\",\n",
+    "                                \"type\": \"function\",\n",
     "                                \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                            },\n",
     "                            {\n",
     "                                \"name\": \"xyzzy\",\n",
+    "                                \"type\": \"function\",\n",
     "                                \"metrics\": {\"time (inc)\": 25.0, \"time\": 5.0},\n",
     "                                \"children\": [\n",
     "                                    {\n",
     "                                        \"name\": \"thud\",\n",
+    "                                        \"type\": \"function\",\n",
     "                                        \"metrics\": {\n",
     "                                            \"time (inc)\": 25.0,\n",
     "                                            \"time\": 5.0,\n",
@@ -331,6 +360,7 @@
     "                                        \"children\": [\n",
     "                                            {\n",
     "                                                \"name\": \"baz\",\n",
+    "                                                \"type\": \"function\",\n",
     "                                                \"metrics\": {\n",
     "                                                    \"time (inc)\": 5.0,\n",
     "                                                    \"time\": 5.0,\n",
@@ -338,6 +368,7 @@
     "                                            },\n",
     "                                            {\n",
     "                                                \"name\": \"garply\",\n",
+    "                                                \"type\": \"function\",\n",
     "                                                \"metrics\": {\n",
     "                                                    \"time (inc)\": 15.0,\n",
     "                                                    \"time\": 15.0,\n",
@@ -351,6 +382,7 @@
     "                    },\n",
     "                    {\n",
     "                        \"name\": \"garply\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 15.0, \"time\": 15.0},\n",
     "                    },\n",
     "                ],\n",
@@ -359,24 +391,29 @@
     "    },\n",
     "    {\n",
     "        \"name\": \"kap\",\n",
+    "        \"type\": \"function\",\n",
     "        \"metrics\": {\"time (inc)\": 30.0, \"time\": 0.0},\n",
     "        \"children\": [\n",
     "            {\n",
     "                \"name\": \"kow\",\n",
+    "                \"type\": \"function\",\n",
     "                \"metrics\": {\"time (inc)\": 15.0, \"time\": 5.0},\n",
     "                \"children\": [\n",
     "                    {\n",
     "                        \"name\": \"krazy\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                    },\n",
     "                    {\n",
     "                        \"name\": \"kraze\",\n",
+    "                        \"type\": \"function\",\n",
     "                        \"metrics\": {\"time (inc)\": 5.0, \"time\": 5.0},\n",
     "                    },\n",
     "                ],\n",
     "            },\n",
     "            {\n",
     "                \"name\": \"kat\",\n",
+    "                \"type\": \"function\",\n",
     "                \"metrics\": {\"time (inc)\": 15.0, \"time\": 15.0},\n",
     "            },\n",
     "        ],\n",
@@ -467,7 +504,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.5"
+   "version": "3.7.2"
   }
  },
  "nbformat": 4,
diff --git a/hatchet/cython_modules/graphframe_modules.c b/hatchet/cython_modules/graphframe_modules.c
index 13b9601..e1e492e 100644
--- a/hatchet/cython_modules/graphframe_modules.c
+++ b/hatchet/cython_modules/graphframe_modules.c
@@ -1,26 +1,4 @@
-/* Generated by Cython 0.29.20 */
-
-/* BEGIN: Cython Metadata
-{
-    "distutils": {
-        "depends": [],
-        "extra_compile_args": [
-            "-fopenmp"
-        ],
-        "extra_link_args": [
-            "-fopenmp"
-        ],
-        "libraries": [
-            "m"
-        ],
-        "name": "graphframe_modules",
-        "sources": [
-            "graphframe_modules.pyx"
-        ]
-    },
-    "module_name": "graphframe_modules"
-}
-END: Cython Metadata */
+/* Generated by Cython 0.29.16 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
@@ -29,8 +7,8 @@ END: Cython Metadata */
 #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
     #error Cython requires Python 2.6+ or Python 3.3+.
 #else
-#define CYTHON_ABI "0_29_20"
-#define CYTHON_HEX_VERSION 0x001D14F0
+#define CYTHON_ABI "0_29_16"
+#define CYTHON_HEX_VERSION 0x001D10F0
 #define CYTHON_FUTURE_DIVISION 0
 #include <stddef.h>
 #ifndef offsetof
@@ -520,13 +498,6 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
 #ifndef PySet_CheckExact
   #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
 #endif
-#if PY_VERSION_HEX >= 0x030900A4
-  #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt)
-  #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size)
-#else
-  #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
-  #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size)
-#endif
 #if CYTHON_ASSUME_SAFE_MACROS
   #define __Pyx_PySequence_SIZE(seq)  Py_SIZE(seq)
 #else
@@ -607,10 +578,11 @@ static CYTHON_INLINE float __PYX_NAN() {
 #define __Pyx_truncl truncl
 #endif
 
-#define __PYX_MARK_ERR_POS(f_index, lineno) \
-    { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; }
+
 #define __PYX_ERR(f_index, lineno, Ln_error) \
-    { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; }
+{ \
+  __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \
+}
 
 #ifndef __PYX_EXTERN_C
   #ifdef __cplusplus
@@ -620,8 +592,8 @@ static CYTHON_INLINE float __PYX_NAN() {
   #endif
 #endif
 
-#define __PYX_HAVE__graphframe_modules
-#define __PYX_HAVE_API__graphframe_modules
+#define __PYX_HAVE__hatchet__cython_modules__graphframe_modules
+#define __PYX_HAVE_API__hatchet__cython_modules__graphframe_modules
 /* Early includes */
 #include <math.h>
 #include "pythread.h"
@@ -1508,7 +1480,7 @@ static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) {
     if (likely(L->allocated > len)) {
         Py_INCREF(x);
         PyList_SET_ITEM(list, len, x);
-        __Pyx_SET_SIZE(list, len + 1);
+        Py_SIZE(list) = len+1;
         return 0;
     }
     return PyList_Append(list, x);
@@ -1546,7 +1518,7 @@ static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) {
     if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) {
         Py_INCREF(x);
         PyList_SET_ITEM(list, len, x);
-        __Pyx_SET_SIZE(list, len + 1);
+        Py_SIZE(list) = len+1;
         return 0;
     }
     return PyList_Append(list, x);
@@ -1578,9 +1550,6 @@ static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_nam
 /* SetVTable.proto */
 static int __Pyx_SetVtable(PyObject *dict, void *vtable);
 
-/* PyObjectGetAttrStrNoError.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name);
-
 /* SetupReduce.proto */
 static int __Pyx_setup_reduce(PyObject* type_obj);
 
@@ -1668,7 +1637,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
                 PyObject *original_obj);
 
 /* ObjectToMemviewSlice.proto */
-static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_char(PyObject *, int writable_flag);
+static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_short(PyObject *, int writable_flag);
 
 /* ObjectToMemviewSlice.proto */
 static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_long__const__(PyObject *, int writable_flag);
@@ -1727,7 +1696,7 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo
 
 /* Module declarations from 'libc.math' */
 
-/* Module declarations from 'graphframe_modules' */
+/* Module declarations from 'hatchet.cython_modules.graphframe_modules' */
 static PyTypeObject *__pyx_array_type = 0;
 static PyTypeObject *__pyx_MemviewEnum_type = 0;
 static PyTypeObject *__pyx_memoryview_type = 0;
@@ -1739,8 +1708,8 @@ static PyObject *contiguous = 0;
 static PyObject *indirect_contiguous = 0;
 static int __pyx_memoryview_thread_locks_used;
 static PyThread_type_lock __pyx_memoryview_thread_locks[8];
-static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice, __Pyx_memviewslice, long const , long const , int __pyx_skip_dispatch); /*proto*/
-static PyObject *__pyx_f_18graphframe_modules_binary_search(__Pyx_memviewslice, long const , unsigned PY_LONG_LONG const ); /*proto*/
+static PyObject *__pyx_f_7hatchet_14cython_modules_18graphframe_modules_fast_not_isin(__Pyx_memviewslice, __Pyx_memviewslice, long const , long const , int __pyx_skip_dispatch); /*proto*/
+static PyObject *__pyx_f_7hatchet_14cython_modules_18graphframe_modules_binary_search(__Pyx_memviewslice, long const , unsigned PY_LONG_LONG const ); /*proto*/
 static struct __pyx_array_obj *__pyx_array_new(PyObject *, Py_ssize_t, char *, char *, char *); /*proto*/
 static void *__pyx_align_pointer(void *, size_t); /*proto*/
 static PyObject *__pyx_memoryview_new(PyObject *, int, int, __Pyx_TypeInfo *); /*proto*/
@@ -1774,14 +1743,14 @@ static void __pyx_memoryview_refcount_objects_in_slice(char *, Py_ssize_t *, Py_
 static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *, int, size_t, void *, int); /*proto*/
 static void __pyx_memoryview__slice_assign_scalar(char *, Py_ssize_t *, Py_ssize_t *, int, size_t, void *); /*proto*/
 static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *, PyObject *); /*proto*/
-static __Pyx_TypeInfo __Pyx_TypeInfo_char = { "char", NULL, sizeof(char), { 0 }, 0, 'H', IS_UNSIGNED(char), 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_short = { "short", NULL, sizeof(short), { 0 }, 0, IS_UNSIGNED(short) ? 'U' : 'I', IS_UNSIGNED(short), 0 };
 static __Pyx_TypeInfo __Pyx_TypeInfo_long__const__ = { "const long", NULL, sizeof(long const ), { 0 }, 0, IS_UNSIGNED(long const ) ? 'U' : 'I', IS_UNSIGNED(long const ), 0 };
 static __Pyx_TypeInfo __Pyx_TypeInfo_unsigned_PY_LONG_LONG__const__ = { "const unsigned long long", NULL, sizeof(unsigned PY_LONG_LONG const ), { 0 }, 0, IS_UNSIGNED(unsigned PY_LONG_LONG const ) ? 'U' : 'I', IS_UNSIGNED(unsigned PY_LONG_LONG const ), 0 };
-#define __Pyx_MODULE_NAME "graphframe_modules"
-extern int __pyx_module_is_main_graphframe_modules;
-int __pyx_module_is_main_graphframe_modules = 0;
+#define __Pyx_MODULE_NAME "hatchet.cython_modules.graphframe_modules"
+extern int __pyx_module_is_main_hatchet__cython_modules__graphframe_modules;
+int __pyx_module_is_main_hatchet__cython_modules__graphframe_modules = 0;
 
-/* Implementation of 'graphframe_modules' */
+/* Implementation of 'hatchet.cython_modules.graphframe_modules' */
 static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_MemoryError;
@@ -1812,7 +1781,6 @@ static const char __pyx_k_step[] = "step";
 static const char __pyx_k_stop[] = "stop";
 static const char __pyx_k_test[] = "__test__";
 static const char __pyx_k_ASCII[] = "ASCII";
-static const char __pyx_k_add_L[] = "add_L";
 static const char __pyx_k_class[] = "__class__";
 static const char __pyx_k_dtype[] = "dtype";
 static const char __pyx_k_error[] = "error";
@@ -1864,7 +1832,6 @@ static const char __pyx_k_setstate_cython[] = "__setstate_cython__";
 static const char __pyx_k_pyx_unpickle_Enum[] = "__pyx_unpickle_Enum";
 static const char __pyx_k_self_missing_node[] = "self_missing_node";
 static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback";
-static const char __pyx_k_graphframe_modules[] = "graphframe_modules";
 static const char __pyx_k_strided_and_direct[] = "<strided and direct>";
 static const char __pyx_k_strided_and_indirect[] = "<strided and indirect>";
 static const char __pyx_k_contiguous_and_direct[] = "<contiguous and direct>";
@@ -1874,6 +1841,7 @@ static const char __pyx_k_MemoryView_of_r_at_0x_x[] = "<MemoryView of %r at 0x%x
 static const char __pyx_k_contiguous_and_indirect[] = "<contiguous and indirect>";
 static const char __pyx_k_Cannot_index_with_type_s[] = "Cannot index with type '%s'";
 static const char __pyx_k_Invalid_shape_in_axis_d_d[] = "Invalid shape in axis %d: %d.";
+static const char __pyx_k_insert_one_for_self_nodes[] = "insert_one_for_self_nodes";
 static const char __pyx_k_itemsize_0_for_cython_array[] = "itemsize <= 0 for cython.array";
 static const char __pyx_k_unable_to_allocate_array_data[] = "unable to allocate array data.";
 static const char __pyx_k_strided_and_direct_or_indirect[] = "<strided and direct or indirect>";
@@ -1888,6 +1856,7 @@ static const char __pyx_k_Invalid_mode_expected_c_or_fortr[] = "Invalid mode, ex
 static const char __pyx_k_Out_of_bounds_on_buffer_access_a[] = "Out of bounds on buffer access (axis %d)";
 static const char __pyx_k_Unable_to_convert_item_to_object[] = "Unable to convert item to object";
 static const char __pyx_k_got_differing_extents_in_dimensi[] = "got differing extents in dimension %d (got %d and %d)";
+static const char __pyx_k_hatchet_cython_modules_graphfram[] = "hatchet.cython_modules.graphframe_modules";
 static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __reduce__ due to non-trivial __cinit__";
 static const char __pyx_k_unable_to_allocate_shape_and_str[] = "unable to allocate shape and strides.";
 static PyObject *__pyx_n_s_ASCII;
@@ -1913,7 +1882,6 @@ static PyObject *__pyx_n_s_TypeError;
 static PyObject *__pyx_kp_s_Unable_to_convert_item_to_object;
 static PyObject *__pyx_n_s_ValueError;
 static PyObject *__pyx_n_s_View_MemoryView;
-static PyObject *__pyx_n_s_add_L;
 static PyObject *__pyx_n_s_allocate_buffer;
 static PyObject *__pyx_n_s_arr1;
 static PyObject *__pyx_n_s_arr1_len;
@@ -1939,11 +1907,12 @@ static PyObject *__pyx_n_s_fortran;
 static PyObject *__pyx_n_u_fortran;
 static PyObject *__pyx_n_s_getstate;
 static PyObject *__pyx_kp_s_got_differing_extents_in_dimensi;
-static PyObject *__pyx_n_s_graphframe_modules;
 static PyObject *__pyx_kp_s_graphframe_modules_pyx;
+static PyObject *__pyx_n_s_hatchet_cython_modules_graphfram;
 static PyObject *__pyx_n_s_i;
 static PyObject *__pyx_n_s_id;
 static PyObject *__pyx_n_s_import;
+static PyObject *__pyx_n_s_insert_one_for_self_nodes;
 static PyObject *__pyx_n_s_itemsize;
 static PyObject *__pyx_kp_s_itemsize_0_for_cython_array;
 static PyObject *__pyx_n_s_main;
@@ -1992,8 +1961,8 @@ static PyObject *__pyx_kp_s_unable_to_allocate_shape_and_str;
 static PyObject *__pyx_n_s_unpack;
 static PyObject *__pyx_n_s_update;
 static PyObject *__pyx_n_s_zeros;
-static PyObject *__pyx_pf_18graphframe_modules_add_L(CYTHON_UNUSED PyObject *__pyx_self, long __pyx_v_snio_len, __Pyx_memviewslice __pyx_v_self_missing_node, __Pyx_memviewslice __pyx_v_snio_indices); /* proto */
-static PyObject *__pyx_pf_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long __pyx_v_arr1_len, long __pyx_v_arr2_len); /* proto */
+static PyObject *__pyx_pf_7hatchet_14cython_modules_18graphframe_modules_insert_one_for_self_nodes(CYTHON_UNUSED PyObject *__pyx_self, long __pyx_v_snio_len, __Pyx_memviewslice __pyx_v_self_missing_node, __Pyx_memviewslice __pyx_v_snio_indices); /* proto */
+static PyObject *__pyx_pf_7hatchet_14cython_modules_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long __pyx_v_arr1_len, long __pyx_v_arr2_len); /* proto */
 static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, PyObject *__pyx_v_format, PyObject *__pyx_v_mode, int __pyx_v_allocate_buffer); /* proto */
 static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(struct __pyx_array_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
 static void __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(struct __pyx_array_obj *__pyx_v_self); /* proto */
@@ -2073,27 +2042,25 @@ static PyObject *__pyx_codeobj__20;
 static PyObject *__pyx_codeobj__27;
 /* Late includes */
 
-/* "graphframe_modules.pyx":7
- * 
+/* "hatchet/cython_modules/graphframe_modules.pyx":13
+ * # Description: All cython code related to graphframe.py
  * @cython.boundscheck(False)
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ * def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):
- *       self_missing_node[snio_indices[i]] = 'L'
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_18graphframe_modules_1add_L(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_18graphframe_modules_1add_L = {"add_L", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18graphframe_modules_1add_L, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_18graphframe_modules_1add_L(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_1insert_one_for_self_nodes(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7hatchet_14cython_modules_18graphframe_modules_insert_one_for_self_nodes[] = "Adds a '1' where rows are in self but not in other.";
+static PyMethodDef __pyx_mdef_7hatchet_14cython_modules_18graphframe_modules_1insert_one_for_self_nodes = {"insert_one_for_self_nodes", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_1insert_one_for_self_nodes, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7hatchet_14cython_modules_18graphframe_modules_insert_one_for_self_nodes};
+static PyObject *__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_1insert_one_for_self_nodes(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   long __pyx_v_snio_len;
   __Pyx_memviewslice __pyx_v_self_missing_node = { 0, 0, { 0 }, { 0 }, { 0 } };
   __Pyx_memviewslice __pyx_v_snio_indices = { 0, 0, { 0 }, { 0 }, { 0 } };
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("add_L (wrapper)", 0);
+  __Pyx_RefNannySetupContext("insert_one_for_self_nodes (wrapper)", 0);
   {
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_snio_len,&__pyx_n_s_self_missing_node,&__pyx_n_s_snio_indices,0};
     PyObject* values[3] = {0,0,0};
@@ -2119,17 +2086,17 @@ static PyObject *__pyx_pw_18graphframe_modules_1add_L(PyObject *__pyx_self, PyOb
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self_missing_node)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("add_L", 1, 3, 3, 1); __PYX_ERR(0, 7, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("insert_one_for_self_nodes", 1, 3, 3, 1); __PYX_ERR(0, 13, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
         if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_snio_indices)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("add_L", 1, 3, 3, 2); __PYX_ERR(0, 7, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("insert_one_for_self_nodes", 1, 3, 3, 2); __PYX_ERR(0, 13, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add_L") < 0)) __PYX_ERR(0, 7, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "insert_one_for_self_nodes") < 0)) __PYX_ERR(0, 13, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
       goto __pyx_L5_argtuple_error;
@@ -2138,26 +2105,26 @@ static PyObject *__pyx_pw_18graphframe_modules_1add_L(PyObject *__pyx_self, PyOb
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
       values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
     }
-    __pyx_v_snio_len = __Pyx_PyInt_As_long(values[0]); if (unlikely((__pyx_v_snio_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 7, __pyx_L3_error)
-    __pyx_v_self_missing_node = __Pyx_PyObject_to_MemoryviewSlice_ds_char(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_self_missing_node.memview)) __PYX_ERR(0, 7, __pyx_L3_error)
-    __pyx_v_snio_indices = __Pyx_PyObject_to_MemoryviewSlice_ds_long__const__(values[2], 0); if (unlikely(!__pyx_v_snio_indices.memview)) __PYX_ERR(0, 7, __pyx_L3_error)
+    __pyx_v_snio_len = __Pyx_PyInt_As_long(values[0]); if (unlikely((__pyx_v_snio_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 13, __pyx_L3_error)
+    __pyx_v_self_missing_node = __Pyx_PyObject_to_MemoryviewSlice_ds_short(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_self_missing_node.memview)) __PYX_ERR(0, 13, __pyx_L3_error)
+    __pyx_v_snio_indices = __Pyx_PyObject_to_MemoryviewSlice_ds_long__const__(values[2], 0); if (unlikely(!__pyx_v_snio_indices.memview)) __PYX_ERR(0, 13, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("add_L", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 7, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("insert_one_for_self_nodes", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 13, __pyx_L3_error)
   __pyx_L3_error:;
-  __Pyx_AddTraceback("graphframe_modules.add_L", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("hatchet.cython_modules.graphframe_modules.insert_one_for_self_nodes", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_18graphframe_modules_add_L(__pyx_self, __pyx_v_snio_len, __pyx_v_self_missing_node, __pyx_v_snio_indices);
+  __pyx_r = __pyx_pf_7hatchet_14cython_modules_18graphframe_modules_insert_one_for_self_nodes(__pyx_self, __pyx_v_snio_len, __pyx_v_self_missing_node, __pyx_v_snio_indices);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_18graphframe_modules_add_L(CYTHON_UNUSED PyObject *__pyx_self, long __pyx_v_snio_len, __Pyx_memviewslice __pyx_v_self_missing_node, __Pyx_memviewslice __pyx_v_snio_indices) {
+static PyObject *__pyx_pf_7hatchet_14cython_modules_18graphframe_modules_insert_one_for_self_nodes(CYTHON_UNUSED PyObject *__pyx_self, long __pyx_v_snio_len, __Pyx_memviewslice __pyx_v_self_missing_node, __Pyx_memviewslice __pyx_v_snio_indices) {
   long __pyx_v_i;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -2166,13 +2133,13 @@ static PyObject *__pyx_pf_18graphframe_modules_add_L(CYTHON_UNUSED PyObject *__p
   long __pyx_t_3;
   Py_ssize_t __pyx_t_4;
   Py_ssize_t __pyx_t_5;
-  __Pyx_RefNannySetupContext("add_L", 0);
+  __Pyx_RefNannySetupContext("insert_one_for_self_nodes", 0);
 
-  /* "graphframe_modules.pyx":8
- * @cython.boundscheck(False)
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):
+  /* "hatchet/cython_modules/graphframe_modules.pyx":15
+ * def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):             # <<<<<<<<<<<<<<
- *       self_missing_node[snio_indices[i]] = 'L'
+ *         self_missing_node[snio_indices[i]] = 1
  * 
  */
   __pyx_t_1 = __pyx_v_snio_len;
@@ -2180,26 +2147,26 @@ static PyObject *__pyx_pf_18graphframe_modules_add_L(CYTHON_UNUSED PyObject *__p
   for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
     __pyx_v_i = __pyx_t_3;
 
-    /* "graphframe_modules.pyx":9
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):
+    /* "hatchet/cython_modules/graphframe_modules.pyx":16
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):
- *       self_missing_node[snio_indices[i]] = 'L'             # <<<<<<<<<<<<<<
+ *         self_missing_node[snio_indices[i]] = 1             # <<<<<<<<<<<<<<
  * 
- * # Complexity: O(nlogn)
+ * cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):
  */
     __pyx_t_4 = __pyx_v_i;
     if (__pyx_t_4 < 0) __pyx_t_4 += __pyx_v_snio_indices.shape[0];
     __pyx_t_5 = (*((long const  *) ( /* dim=0 */ (__pyx_v_snio_indices.data + __pyx_t_4 * __pyx_v_snio_indices.strides[0]) )));
     if (__pyx_t_5 < 0) __pyx_t_5 += __pyx_v_self_missing_node.shape[0];
-    *((char *) ( /* dim=0 */ (__pyx_v_self_missing_node.data + __pyx_t_5 * __pyx_v_self_missing_node.strides[0]) )) = 'L';
+    *((short *) ( /* dim=0 */ (__pyx_v_self_missing_node.data + __pyx_t_5 * __pyx_v_self_missing_node.strides[0]) )) = 1;
   }
 
-  /* "graphframe_modules.pyx":7
- * 
+  /* "hatchet/cython_modules/graphframe_modules.pyx":13
+ * # Description: All cython code related to graphframe.py
  * @cython.boundscheck(False)
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ * def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):
- *       self_missing_node[snio_indices[i]] = 'L'
  */
 
   /* function exit code */
@@ -2211,16 +2178,16 @@ static PyObject *__pyx_pf_18graphframe_modules_add_L(CYTHON_UNUSED PyObject *__p
   return __pyx_r;
 }
 
-/* "graphframe_modules.pyx":12
+/* "hatchet/cython_modules/graphframe_modules.pyx":18
+ *         self_missing_node[snio_indices[i]] = 1
  * 
- * # Complexity: O(nlogn)
  * cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):             # <<<<<<<<<<<<<<
- *     result = np.zeros(len(arr1), dtype=np.bool_)
- *     cdef long index = -1
+ *     """Check if elements in arr1 exist in arr2.
+ * 
  */
 
-static PyObject *__pyx_pw_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long const __pyx_v_arr1_len, long const __pyx_v_arr2_len, CYTHON_UNUSED int __pyx_skip_dispatch) {
+static PyObject *__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_f_7hatchet_14cython_modules_18graphframe_modules_fast_not_isin(__Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long const __pyx_v_arr1_len, long const __pyx_v_arr2_len, CYTHON_UNUSED int __pyx_skip_dispatch) {
   PyObject *__pyx_v_result = NULL;
   long __pyx_v_index;
   unsigned PY_LONG_LONG __pyx_v_prior;
@@ -2240,43 +2207,52 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
   Py_ssize_t __pyx_t_11;
   int __pyx_t_12;
   int __pyx_t_13;
-  unsigned PY_LONG_LONG __pyx_t_14;
-  long __pyx_t_15;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+  Py_ssize_t __pyx_t_14;
+  Py_ssize_t __pyx_t_15;
+  unsigned PY_LONG_LONG __pyx_t_16;
+  Py_ssize_t __pyx_t_17;
+  Py_ssize_t __pyx_t_18;
+  Py_ssize_t __pyx_t_19;
+  Py_ssize_t __pyx_t_20;
+  long __pyx_t_21;
+  Py_ssize_t __pyx_t_22;
+  Py_ssize_t __pyx_t_23;
+  Py_ssize_t __pyx_t_24;
+  Py_ssize_t __pyx_t_25;
+  Py_ssize_t __pyx_t_26;
+  Py_ssize_t __pyx_t_27;
   __Pyx_RefNannySetupContext("fast_not_isin", 0);
 
-  /* "graphframe_modules.pyx":13
- * # Complexity: O(nlogn)
- * cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):
+  /* "hatchet/cython_modules/graphframe_modules.pyx":32
+ *             the function. True indicates that an element is not in arr2.
+ *     """
  *     result = np.zeros(len(arr1), dtype=np.bool_)             # <<<<<<<<<<<<<<
  *     cdef long index = -1
  *     cdef unsigned long long prior = -1
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_t_3 = __Pyx_MemoryView_Len(__pyx_v_arr1); 
-  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_bool); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_bool); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_6) < 0) __PYX_ERR(0, 13, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_6) < 0) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_4, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 13, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_4, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 32, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -2284,8 +2260,8 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
   __pyx_v_result = __pyx_t_6;
   __pyx_t_6 = 0;
 
-  /* "graphframe_modules.pyx":14
- * cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):
+  /* "hatchet/cython_modules/graphframe_modules.pyx":33
+ *     """
  *     result = np.zeros(len(arr1), dtype=np.bool_)
  *     cdef long index = -1             # <<<<<<<<<<<<<<
  *     cdef unsigned long long prior = -1
@@ -2293,7 +2269,7 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
  */
   __pyx_v_index = -1L;
 
-  /* "graphframe_modules.pyx":15
+  /* "hatchet/cython_modules/graphframe_modules.pyx":34
  *     result = np.zeros(len(arr1), dtype=np.bool_)
  *     cdef long index = -1
  *     cdef unsigned long long prior = -1             # <<<<<<<<<<<<<<
@@ -2302,7 +2278,7 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
  */
   __pyx_v_prior = -1LL;
 
-  /* "graphframe_modules.pyx":16
+  /* "hatchet/cython_modules/graphframe_modules.pyx":35
  *     cdef long index = -1
  *     cdef unsigned long long prior = -1
  *     cdef long i = 0             # <<<<<<<<<<<<<<
@@ -2311,24 +2287,24 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
  */
   __pyx_v_i = 0;
 
-  /* "graphframe_modules.pyx":18
+  /* "hatchet/cython_modules/graphframe_modules.pyx":37
  *     cdef long i = 0
  * 
  *     for i in range(arr1_len):             # <<<<<<<<<<<<<<
- *       # mini optimization: don't perform binsearch if we already know node is/isnot in graph
- *       if prior == arr1[i][0]:
+ *         # mini optimization: don't perform binsearch if we already know node is/isnot in graph
+ *         if prior == arr1[i][0]:
  */
   __pyx_t_7 = __pyx_v_arr1_len;
   __pyx_t_8 = __pyx_t_7;
   for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
     __pyx_v_i = __pyx_t_9;
 
-    /* "graphframe_modules.pyx":20
+    /* "hatchet/cython_modules/graphframe_modules.pyx":39
  *     for i in range(arr1_len):
- *       # mini optimization: don't perform binsearch if we already know node is/isnot in graph
- *       if prior == arr1[i][0]:             # <<<<<<<<<<<<<<
- *         result[arr1[i][1]] = result[arr1[i-1][1]]
- *       else:
+ *         # mini optimization: don't perform binsearch if we already know node is/isnot in graph
+ *         if prior == arr1[i][0]:             # <<<<<<<<<<<<<<
+ *             result[arr1[i][1]] = result[arr1[i-1][1]]
+ *         else:
  */
     __pyx_t_10 = __pyx_v_i;
     __pyx_t_11 = 0;
@@ -2343,212 +2319,212 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
     } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
     if (unlikely(__pyx_t_12 != -1)) {
       __Pyx_RaiseBufferIndexError(__pyx_t_12);
-      __PYX_ERR(0, 20, __pyx_L1_error)
+      __PYX_ERR(0, 39, __pyx_L1_error)
     }
     __pyx_t_13 = ((__pyx_v_prior == (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_10 * __pyx_v_arr1.strides[0]) ) + __pyx_t_11 * __pyx_v_arr1.strides[1]) )))) != 0);
     if (__pyx_t_13) {
 
-      /* "graphframe_modules.pyx":21
- *       # mini optimization: don't perform binsearch if we already know node is/isnot in graph
- *       if prior == arr1[i][0]:
- *         result[arr1[i][1]] = result[arr1[i-1][1]]             # <<<<<<<<<<<<<<
- *       else:
- *         index = binary_search(arr2, arr2_len, arr1[i][0])
+      /* "hatchet/cython_modules/graphframe_modules.pyx":40
+ *         # mini optimization: don't perform binsearch if we already know node is/isnot in graph
+ *         if prior == arr1[i][0]:
+ *             result[arr1[i][1]] = result[arr1[i-1][1]]             # <<<<<<<<<<<<<<
+ *         else:
+ *             index = binary_search(arr2, arr2_len, arr1[i][0])
  */
-      __pyx_t_11 = (__pyx_v_i - 1);
-      __pyx_t_10 = 1;
+      __pyx_t_14 = (__pyx_v_i - 1);
+      __pyx_t_15 = 1;
       __pyx_t_12 = -1;
-      if (__pyx_t_11 < 0) {
-        __pyx_t_11 += __pyx_v_arr1.shape[0];
-        if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 0;
-      } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-      if (__pyx_t_10 < 0) {
-        __pyx_t_10 += __pyx_v_arr1.shape[1];
-        if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 1;
-      } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+      if (__pyx_t_14 < 0) {
+        __pyx_t_14 += __pyx_v_arr1.shape[0];
+        if (unlikely(__pyx_t_14 < 0)) __pyx_t_12 = 0;
+      } else if (unlikely(__pyx_t_14 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+      if (__pyx_t_15 < 0) {
+        __pyx_t_15 += __pyx_v_arr1.shape[1];
+        if (unlikely(__pyx_t_15 < 0)) __pyx_t_12 = 1;
+      } else if (unlikely(__pyx_t_15 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
       if (unlikely(__pyx_t_12 != -1)) {
         __Pyx_RaiseBufferIndexError(__pyx_t_12);
-        __PYX_ERR(0, 21, __pyx_L1_error)
+        __PYX_ERR(0, 40, __pyx_L1_error)
       }
-      __pyx_t_14 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_11 * __pyx_v_arr1.strides[0]) ) + __pyx_t_10 * __pyx_v_arr1.strides[1]) )));
-      __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_result, __pyx_t_14, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 21, __pyx_L1_error)
+      __pyx_t_16 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_14 * __pyx_v_arr1.strides[0]) ) + __pyx_t_15 * __pyx_v_arr1.strides[1]) )));
+      __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_result, __pyx_t_16, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 40, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_10 = __pyx_v_i;
-      __pyx_t_11 = 1;
+      __pyx_t_17 = __pyx_v_i;
+      __pyx_t_18 = 1;
       __pyx_t_12 = -1;
-      if (__pyx_t_10 < 0) {
-        __pyx_t_10 += __pyx_v_arr1.shape[0];
-        if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 0;
-      } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-      if (__pyx_t_11 < 0) {
-        __pyx_t_11 += __pyx_v_arr1.shape[1];
-        if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 1;
-      } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+      if (__pyx_t_17 < 0) {
+        __pyx_t_17 += __pyx_v_arr1.shape[0];
+        if (unlikely(__pyx_t_17 < 0)) __pyx_t_12 = 0;
+      } else if (unlikely(__pyx_t_17 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+      if (__pyx_t_18 < 0) {
+        __pyx_t_18 += __pyx_v_arr1.shape[1];
+        if (unlikely(__pyx_t_18 < 0)) __pyx_t_12 = 1;
+      } else if (unlikely(__pyx_t_18 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
       if (unlikely(__pyx_t_12 != -1)) {
         __Pyx_RaiseBufferIndexError(__pyx_t_12);
-        __PYX_ERR(0, 21, __pyx_L1_error)
+        __PYX_ERR(0, 40, __pyx_L1_error)
       }
-      __pyx_t_14 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_10 * __pyx_v_arr1.strides[0]) ) + __pyx_t_11 * __pyx_v_arr1.strides[1]) )));
-      if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_14, __pyx_t_6, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 21, __pyx_L1_error)
+      __pyx_t_16 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_17 * __pyx_v_arr1.strides[0]) ) + __pyx_t_18 * __pyx_v_arr1.strides[1]) )));
+      if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_16, __pyx_t_6, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 40, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
 
-      /* "graphframe_modules.pyx":20
+      /* "hatchet/cython_modules/graphframe_modules.pyx":39
  *     for i in range(arr1_len):
- *       # mini optimization: don't perform binsearch if we already know node is/isnot in graph
- *       if prior == arr1[i][0]:             # <<<<<<<<<<<<<<
- *         result[arr1[i][1]] = result[arr1[i-1][1]]
- *       else:
+ *         # mini optimization: don't perform binsearch if we already know node is/isnot in graph
+ *         if prior == arr1[i][0]:             # <<<<<<<<<<<<<<
+ *             result[arr1[i][1]] = result[arr1[i-1][1]]
+ *         else:
  */
       goto __pyx_L5;
     }
 
-    /* "graphframe_modules.pyx":23
- *         result[arr1[i][1]] = result[arr1[i-1][1]]
- *       else:
- *         index = binary_search(arr2, arr2_len, arr1[i][0])             # <<<<<<<<<<<<<<
- *         if index == -1:
- *             result[arr1[i][1]] = True
+    /* "hatchet/cython_modules/graphframe_modules.pyx":42
+ *             result[arr1[i][1]] = result[arr1[i-1][1]]
+ *         else:
+ *             index = binary_search(arr2, arr2_len, arr1[i][0])             # <<<<<<<<<<<<<<
+ *             if index == -1:
+ *                 result[arr1[i][1]] = True
  */
     /*else*/ {
-      __pyx_t_11 = __pyx_v_i;
-      __pyx_t_10 = 0;
+      __pyx_t_19 = __pyx_v_i;
+      __pyx_t_20 = 0;
       __pyx_t_12 = -1;
-      if (__pyx_t_11 < 0) {
-        __pyx_t_11 += __pyx_v_arr1.shape[0];
-        if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 0;
-      } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-      if (__pyx_t_10 < 0) {
-        __pyx_t_10 += __pyx_v_arr1.shape[1];
-        if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 1;
-      } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+      if (__pyx_t_19 < 0) {
+        __pyx_t_19 += __pyx_v_arr1.shape[0];
+        if (unlikely(__pyx_t_19 < 0)) __pyx_t_12 = 0;
+      } else if (unlikely(__pyx_t_19 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+      if (__pyx_t_20 < 0) {
+        __pyx_t_20 += __pyx_v_arr1.shape[1];
+        if (unlikely(__pyx_t_20 < 0)) __pyx_t_12 = 1;
+      } else if (unlikely(__pyx_t_20 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
       if (unlikely(__pyx_t_12 != -1)) {
         __Pyx_RaiseBufferIndexError(__pyx_t_12);
-        __PYX_ERR(0, 23, __pyx_L1_error)
+        __PYX_ERR(0, 42, __pyx_L1_error)
       }
-      __pyx_t_6 = __pyx_f_18graphframe_modules_binary_search(__pyx_v_arr2, __pyx_v_arr2_len, (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_11 * __pyx_v_arr1.strides[0]) ) + __pyx_t_10 * __pyx_v_arr1.strides[1]) )))); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error)
+      __pyx_t_6 = __pyx_f_7hatchet_14cython_modules_18graphframe_modules_binary_search(__pyx_v_arr2, __pyx_v_arr2_len, (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_19 * __pyx_v_arr1.strides[0]) ) + __pyx_t_20 * __pyx_v_arr1.strides[1]) )))); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 42, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_15 = __Pyx_PyInt_As_long(__pyx_t_6); if (unlikely((__pyx_t_15 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error)
+      __pyx_t_21 = __Pyx_PyInt_As_long(__pyx_t_6); if (unlikely((__pyx_t_21 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 42, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_v_index = __pyx_t_15;
+      __pyx_v_index = __pyx_t_21;
 
-      /* "graphframe_modules.pyx":24
- *       else:
- *         index = binary_search(arr2, arr2_len, arr1[i][0])
- *         if index == -1:             # <<<<<<<<<<<<<<
- *             result[arr1[i][1]] = True
+      /* "hatchet/cython_modules/graphframe_modules.pyx":43
  *         else:
+ *             index = binary_search(arr2, arr2_len, arr1[i][0])
+ *             if index == -1:             # <<<<<<<<<<<<<<
+ *                 result[arr1[i][1]] = True
+ *             else:
  */
       __pyx_t_13 = ((__pyx_v_index == -1L) != 0);
       if (__pyx_t_13) {
 
-        /* "graphframe_modules.pyx":25
- *         index = binary_search(arr2, arr2_len, arr1[i][0])
- *         if index == -1:
- *             result[arr1[i][1]] = True             # <<<<<<<<<<<<<<
- *         else:
- *             result[arr1[i][1]] = False
+        /* "hatchet/cython_modules/graphframe_modules.pyx":44
+ *             index = binary_search(arr2, arr2_len, arr1[i][0])
+ *             if index == -1:
+ *                 result[arr1[i][1]] = True             # <<<<<<<<<<<<<<
+ *             else:
+ *                 result[arr1[i][1]] = False
  */
-        __pyx_t_10 = __pyx_v_i;
-        __pyx_t_11 = 1;
+        __pyx_t_22 = __pyx_v_i;
+        __pyx_t_23 = 1;
         __pyx_t_12 = -1;
-        if (__pyx_t_10 < 0) {
-          __pyx_t_10 += __pyx_v_arr1.shape[0];
-          if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 0;
-        } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-        if (__pyx_t_11 < 0) {
-          __pyx_t_11 += __pyx_v_arr1.shape[1];
-          if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 1;
-        } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+        if (__pyx_t_22 < 0) {
+          __pyx_t_22 += __pyx_v_arr1.shape[0];
+          if (unlikely(__pyx_t_22 < 0)) __pyx_t_12 = 0;
+        } else if (unlikely(__pyx_t_22 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+        if (__pyx_t_23 < 0) {
+          __pyx_t_23 += __pyx_v_arr1.shape[1];
+          if (unlikely(__pyx_t_23 < 0)) __pyx_t_12 = 1;
+        } else if (unlikely(__pyx_t_23 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
         if (unlikely(__pyx_t_12 != -1)) {
           __Pyx_RaiseBufferIndexError(__pyx_t_12);
-          __PYX_ERR(0, 25, __pyx_L1_error)
+          __PYX_ERR(0, 44, __pyx_L1_error)
         }
-        __pyx_t_14 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_10 * __pyx_v_arr1.strides[0]) ) + __pyx_t_11 * __pyx_v_arr1.strides[1]) )));
-        if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_14, Py_True, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 25, __pyx_L1_error)
-
-        /* "graphframe_modules.pyx":24
- *       else:
- *         index = binary_search(arr2, arr2_len, arr1[i][0])
- *         if index == -1:             # <<<<<<<<<<<<<<
- *             result[arr1[i][1]] = True
+        __pyx_t_16 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_22 * __pyx_v_arr1.strides[0]) ) + __pyx_t_23 * __pyx_v_arr1.strides[1]) )));
+        if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_16, Py_True, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 44, __pyx_L1_error)
+
+        /* "hatchet/cython_modules/graphframe_modules.pyx":43
  *         else:
+ *             index = binary_search(arr2, arr2_len, arr1[i][0])
+ *             if index == -1:             # <<<<<<<<<<<<<<
+ *                 result[arr1[i][1]] = True
+ *             else:
  */
         goto __pyx_L6;
       }
 
-      /* "graphframe_modules.pyx":27
- *             result[arr1[i][1]] = True
- *         else:
- *             result[arr1[i][1]] = False             # <<<<<<<<<<<<<<
+      /* "hatchet/cython_modules/graphframe_modules.pyx":46
+ *                 result[arr1[i][1]] = True
+ *             else:
+ *                 result[arr1[i][1]] = False             # <<<<<<<<<<<<<<
  * 
- *       prior = arr1[i][0]
+ *     prior = arr1[i][0]
  */
       /*else*/ {
-        __pyx_t_11 = __pyx_v_i;
-        __pyx_t_10 = 1;
+        __pyx_t_24 = __pyx_v_i;
+        __pyx_t_25 = 1;
         __pyx_t_12 = -1;
-        if (__pyx_t_11 < 0) {
-          __pyx_t_11 += __pyx_v_arr1.shape[0];
-          if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 0;
-        } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-        if (__pyx_t_10 < 0) {
-          __pyx_t_10 += __pyx_v_arr1.shape[1];
-          if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 1;
-        } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+        if (__pyx_t_24 < 0) {
+          __pyx_t_24 += __pyx_v_arr1.shape[0];
+          if (unlikely(__pyx_t_24 < 0)) __pyx_t_12 = 0;
+        } else if (unlikely(__pyx_t_24 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+        if (__pyx_t_25 < 0) {
+          __pyx_t_25 += __pyx_v_arr1.shape[1];
+          if (unlikely(__pyx_t_25 < 0)) __pyx_t_12 = 1;
+        } else if (unlikely(__pyx_t_25 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
         if (unlikely(__pyx_t_12 != -1)) {
           __Pyx_RaiseBufferIndexError(__pyx_t_12);
-          __PYX_ERR(0, 27, __pyx_L1_error)
+          __PYX_ERR(0, 46, __pyx_L1_error)
         }
-        __pyx_t_14 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_11 * __pyx_v_arr1.strides[0]) ) + __pyx_t_10 * __pyx_v_arr1.strides[1]) )));
-        if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_14, Py_False, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 27, __pyx_L1_error)
+        __pyx_t_16 = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_24 * __pyx_v_arr1.strides[0]) ) + __pyx_t_25 * __pyx_v_arr1.strides[1]) )));
+        if (unlikely(__Pyx_SetItemInt(__pyx_v_result, __pyx_t_16, Py_False, unsigned PY_LONG_LONG const , 0, __Pyx_PyInt_From_unsigned_PY_LONG_LONG, 0, 0, 1) < 0)) __PYX_ERR(0, 46, __pyx_L1_error)
       }
       __pyx_L6:;
     }
     __pyx_L5:;
+  }
 
-    /* "graphframe_modules.pyx":29
- *             result[arr1[i][1]] = False
+  /* "hatchet/cython_modules/graphframe_modules.pyx":48
+ *                 result[arr1[i][1]] = False
  * 
- *       prior = arr1[i][0]             # <<<<<<<<<<<<<<
+ *     prior = arr1[i][0]             # <<<<<<<<<<<<<<
  * 
  *     return result
  */
-    __pyx_t_10 = __pyx_v_i;
-    __pyx_t_11 = 0;
-    __pyx_t_12 = -1;
-    if (__pyx_t_10 < 0) {
-      __pyx_t_10 += __pyx_v_arr1.shape[0];
-      if (unlikely(__pyx_t_10 < 0)) __pyx_t_12 = 0;
-    } else if (unlikely(__pyx_t_10 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
-    if (__pyx_t_11 < 0) {
-      __pyx_t_11 += __pyx_v_arr1.shape[1];
-      if (unlikely(__pyx_t_11 < 0)) __pyx_t_12 = 1;
-    } else if (unlikely(__pyx_t_11 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
-    if (unlikely(__pyx_t_12 != -1)) {
-      __Pyx_RaiseBufferIndexError(__pyx_t_12);
-      __PYX_ERR(0, 29, __pyx_L1_error)
-    }
-    __pyx_v_prior = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_10 * __pyx_v_arr1.strides[0]) ) + __pyx_t_11 * __pyx_v_arr1.strides[1]) )));
+  __pyx_t_26 = __pyx_v_i;
+  __pyx_t_27 = 0;
+  __pyx_t_12 = -1;
+  if (__pyx_t_26 < 0) {
+    __pyx_t_26 += __pyx_v_arr1.shape[0];
+    if (unlikely(__pyx_t_26 < 0)) __pyx_t_12 = 0;
+  } else if (unlikely(__pyx_t_26 >= __pyx_v_arr1.shape[0])) __pyx_t_12 = 0;
+  if (__pyx_t_27 < 0) {
+    __pyx_t_27 += __pyx_v_arr1.shape[1];
+    if (unlikely(__pyx_t_27 < 0)) __pyx_t_12 = 1;
+  } else if (unlikely(__pyx_t_27 >= __pyx_v_arr1.shape[1])) __pyx_t_12 = 1;
+  if (unlikely(__pyx_t_12 != -1)) {
+    __Pyx_RaiseBufferIndexError(__pyx_t_12);
+    __PYX_ERR(0, 48, __pyx_L1_error)
   }
+  __pyx_v_prior = (*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_arr1.data + __pyx_t_26 * __pyx_v_arr1.strides[0]) ) + __pyx_t_27 * __pyx_v_arr1.strides[1]) )));
 
-  /* "graphframe_modules.pyx":31
- *       prior = arr1[i][0]
+  /* "hatchet/cython_modules/graphframe_modules.pyx":50
+ *     prior = arr1[i][0]
  * 
  *     return result             # <<<<<<<<<<<<<<
  * 
- * # basic binary search algorithm
+ * cdef binary_search(const unsigned long long[:,:] array, const long arr_len, const unsigned long long key):
  */
   __Pyx_XDECREF(__pyx_r);
   __Pyx_INCREF(__pyx_v_result);
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "graphframe_modules.pyx":12
+  /* "hatchet/cython_modules/graphframe_modules.pyx":18
+ *         self_missing_node[snio_indices[i]] = 1
  * 
- * # Complexity: O(nlogn)
  * cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):             # <<<<<<<<<<<<<<
- *     result = np.zeros(len(arr1), dtype=np.bool_)
- *     cdef long index = -1
+ *     """Check if elements in arr1 exist in arr2.
+ * 
  */
 
   /* function exit code */
@@ -2558,7 +2534,7 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("hatchet.cython_modules.graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_v_result);
@@ -2568,15 +2544,13 @@ static PyObject *__pyx_f_18graphframe_modules_fast_not_isin(__Pyx_memviewslice _
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7hatchet_14cython_modules_18graphframe_modules_2fast_not_isin[] = "Check if elements in arr1 exist in arr2.\n\n    A fast check to see if each element in arr1 exists in arr2. This returns a\n    vector mask equivalent to what the operation ~df.isin( ... ) would return.\n\n    Arguments:\n        arr1 (unsigned long long [][]): The array of values we are searching for.\n        arr2 (unsigned long long [][]): The sorted array of values we are searching in.\n\n    Returns:\n        (bool []): A boolean mask over arr1 indicating whether each element is or is not in\n            the function. True indicates that an element is not in arr2.\n    ";
+static PyObject *__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_3fast_not_isin(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   __Pyx_memviewslice __pyx_v_arr1 = { 0, 0, { 0 }, { 0 }, { 0 } };
   __Pyx_memviewslice __pyx_v_arr2 = { 0, 0, { 0 }, { 0 }, { 0 } };
   long __pyx_v_arr1_len;
   long __pyx_v_arr2_len;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("fast_not_isin (wrapper)", 0);
@@ -2607,23 +2581,23 @@ static PyObject *__pyx_pw_18graphframe_modules_3fast_not_isin(PyObject *__pyx_se
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arr2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 1); __PYX_ERR(0, 12, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 1); __PYX_ERR(0, 18, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
         if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arr1_len)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 2); __PYX_ERR(0, 12, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 2); __PYX_ERR(0, 18, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  3:
         if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arr2_len)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 3); __PYX_ERR(0, 12, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, 3); __PYX_ERR(0, 18, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fast_not_isin") < 0)) __PYX_ERR(0, 12, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "fast_not_isin") < 0)) __PYX_ERR(0, 18, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -2633,38 +2607,35 @@ static PyObject *__pyx_pw_18graphframe_modules_3fast_not_isin(PyObject *__pyx_se
       values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
-    __pyx_v_arr1 = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_PY_LONG_LONG__const__(values[0], 0); if (unlikely(!__pyx_v_arr1.memview)) __PYX_ERR(0, 12, __pyx_L3_error)
-    __pyx_v_arr2 = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_PY_LONG_LONG__const__(values[1], 0); if (unlikely(!__pyx_v_arr2.memview)) __PYX_ERR(0, 12, __pyx_L3_error)
-    __pyx_v_arr1_len = __Pyx_PyInt_As_long(values[2]); if (unlikely((__pyx_v_arr1_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 12, __pyx_L3_error)
-    __pyx_v_arr2_len = __Pyx_PyInt_As_long(values[3]); if (unlikely((__pyx_v_arr2_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 12, __pyx_L3_error)
+    __pyx_v_arr1 = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_PY_LONG_LONG__const__(values[0], 0); if (unlikely(!__pyx_v_arr1.memview)) __PYX_ERR(0, 18, __pyx_L3_error)
+    __pyx_v_arr2 = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_PY_LONG_LONG__const__(values[1], 0); if (unlikely(!__pyx_v_arr2.memview)) __PYX_ERR(0, 18, __pyx_L3_error)
+    __pyx_v_arr1_len = __Pyx_PyInt_As_long(values[2]); if (unlikely((__pyx_v_arr1_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 18, __pyx_L3_error)
+    __pyx_v_arr2_len = __Pyx_PyInt_As_long(values[3]); if (unlikely((__pyx_v_arr2_len == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 18, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 12, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("fast_not_isin", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 18, __pyx_L3_error)
   __pyx_L3_error:;
-  __Pyx_AddTraceback("graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("hatchet.cython_modules.graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_18graphframe_modules_2fast_not_isin(__pyx_self, __pyx_v_arr1, __pyx_v_arr2, __pyx_v_arr1_len, __pyx_v_arr2_len);
+  __pyx_r = __pyx_pf_7hatchet_14cython_modules_18graphframe_modules_2fast_not_isin(__pyx_self, __pyx_v_arr1, __pyx_v_arr2, __pyx_v_arr1_len, __pyx_v_arr2_len);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long __pyx_v_arr1_len, long __pyx_v_arr2_len) {
+static PyObject *__pyx_pf_7hatchet_14cython_modules_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_arr1, __Pyx_memviewslice __pyx_v_arr2, long __pyx_v_arr1_len, long __pyx_v_arr2_len) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("fast_not_isin", 0);
   __Pyx_XDECREF(__pyx_r);
-  if (unlikely(!__pyx_v_arr1.memview)) { __Pyx_RaiseUnboundLocalError("arr1"); __PYX_ERR(0, 12, __pyx_L1_error) }
-  if (unlikely(!__pyx_v_arr2.memview)) { __Pyx_RaiseUnboundLocalError("arr2"); __PYX_ERR(0, 12, __pyx_L1_error) }
-  __pyx_t_1 = __pyx_f_18graphframe_modules_fast_not_isin(__pyx_v_arr1, __pyx_v_arr2, __pyx_v_arr1_len, __pyx_v_arr2_len, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)
+  if (unlikely(!__pyx_v_arr1.memview)) { __Pyx_RaiseUnboundLocalError("arr1"); __PYX_ERR(0, 18, __pyx_L1_error) }
+  if (unlikely(!__pyx_v_arr2.memview)) { __Pyx_RaiseUnboundLocalError("arr2"); __PYX_ERR(0, 18, __pyx_L1_error) }
+  __pyx_t_1 = __pyx_f_7hatchet_14cython_modules_18graphframe_modules_fast_not_isin(__pyx_v_arr1, __pyx_v_arr2, __pyx_v_arr1_len, __pyx_v_arr2_len, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -2673,7 +2644,7 @@ static PyObject *__pyx_pf_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyOb
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("hatchet.cython_modules.graphframe_modules.fast_not_isin", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __PYX_XDEC_MEMVIEW(&__pyx_v_arr1, 1);
@@ -2683,15 +2654,15 @@ static PyObject *__pyx_pf_18graphframe_modules_2fast_not_isin(CYTHON_UNUSED PyOb
   return __pyx_r;
 }
 
-/* "graphframe_modules.pyx":34
+/* "hatchet/cython_modules/graphframe_modules.pyx":52
+ *     return result
  * 
- * # basic binary search algorithm
  * cdef binary_search(const unsigned long long[:,:] array, const long arr_len, const unsigned long long key):             # <<<<<<<<<<<<<<
- *     # This search returns the index of key if found, -1 if not found
- *     cdef long L = 0
+ *     """Basic Binary Search.
+ * 
  */
 
-static PyObject *__pyx_f_18graphframe_modules_binary_search(__Pyx_memviewslice __pyx_v_array, long const __pyx_v_arr_len, unsigned PY_LONG_LONG const __pyx_v_key) {
+static PyObject *__pyx_f_7hatchet_14cython_modules_18graphframe_modules_binary_search(__Pyx_memviewslice __pyx_v_array, long const __pyx_v_arr_len, unsigned PY_LONG_LONG const __pyx_v_key) {
   long __pyx_v_L;
   long __pyx_v_R;
   long __pyx_v_midpt;
@@ -2701,65 +2672,64 @@ static PyObject *__pyx_f_18graphframe_modules_binary_search(__Pyx_memviewslice _
   Py_ssize_t __pyx_t_2;
   Py_ssize_t __pyx_t_3;
   int __pyx_t_4;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+  Py_ssize_t __pyx_t_5;
+  Py_ssize_t __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("binary_search", 0);
 
-  /* "graphframe_modules.pyx":36
- * cdef binary_search(const unsigned long long[:,:] array, const long arr_len, const unsigned long long key):
- *     # This search returns the index of key if found, -1 if not found
+  /* "hatchet/cython_modules/graphframe_modules.pyx":60
+ *     Returns: The index of key if found, -1 if not found.
+ *     """
  *     cdef long L = 0             # <<<<<<<<<<<<<<
  *     cdef long R = arr_len - 1
  *     cdef long midpt = 0
  */
   __pyx_v_L = 0;
 
-  /* "graphframe_modules.pyx":37
- *     # This search returns the index of key if found, -1 if not found
+  /* "hatchet/cython_modules/graphframe_modules.pyx":61
+ *     """
  *     cdef long L = 0
  *     cdef long R = arr_len - 1             # <<<<<<<<<<<<<<
  *     cdef long midpt = 0
- *     while(L <= R):
+ *     while (L <= R):
  */
   __pyx_v_R = (__pyx_v_arr_len - 1);
 
-  /* "graphframe_modules.pyx":38
+  /* "hatchet/cython_modules/graphframe_modules.pyx":62
  *     cdef long L = 0
  *     cdef long R = arr_len - 1
  *     cdef long midpt = 0             # <<<<<<<<<<<<<<
- *     while(L <= R):
- *       midpt = <long>floor((L+R)/2)
+ *     while (L <= R):
+ *         midpt = <long>floor((L+R)/2)
  */
   __pyx_v_midpt = 0;
 
-  /* "graphframe_modules.pyx":39
+  /* "hatchet/cython_modules/graphframe_modules.pyx":63
  *     cdef long R = arr_len - 1
  *     cdef long midpt = 0
- *     while(L <= R):             # <<<<<<<<<<<<<<
- *       midpt = <long>floor((L+R)/2)
- *       if array[midpt][0] < key:
+ *     while (L <= R):             # <<<<<<<<<<<<<<
+ *         midpt = <long>floor((L+R)/2)
+ *         if array[midpt][0] < key:
  */
   while (1) {
     __pyx_t_1 = ((__pyx_v_L <= __pyx_v_R) != 0);
     if (!__pyx_t_1) break;
 
-    /* "graphframe_modules.pyx":40
+    /* "hatchet/cython_modules/graphframe_modules.pyx":64
  *     cdef long midpt = 0
- *     while(L <= R):
- *       midpt = <long>floor((L+R)/2)             # <<<<<<<<<<<<<<
- *       if array[midpt][0] < key:
- *         L = midpt + 1
+ *     while (L <= R):
+ *         midpt = <long>floor((L+R)/2)             # <<<<<<<<<<<<<<
+ *         if array[midpt][0] < key:
+ *             L = midpt + 1
  */
     __pyx_v_midpt = ((long)floor(__Pyx_div_long((__pyx_v_L + __pyx_v_R), 2)));
 
-    /* "graphframe_modules.pyx":41
- *     while(L <= R):
- *       midpt = <long>floor((L+R)/2)
- *       if array[midpt][0] < key:             # <<<<<<<<<<<<<<
- *         L = midpt + 1
- *       elif array[midpt][0] > key:
+    /* "hatchet/cython_modules/graphframe_modules.pyx":65
+ *     while (L <= R):
+ *         midpt = <long>floor((L+R)/2)
+ *         if array[midpt][0] < key:             # <<<<<<<<<<<<<<
+ *             L = midpt + 1
+ *         elif array[midpt][0] > key:
  */
     __pyx_t_2 = __pyx_v_midpt;
     __pyx_t_3 = 0;
@@ -2774,94 +2744,94 @@ static PyObject *__pyx_f_18graphframe_modules_binary_search(__Pyx_memviewslice _
     } else if (unlikely(__pyx_t_3 >= __pyx_v_array.shape[1])) __pyx_t_4 = 1;
     if (unlikely(__pyx_t_4 != -1)) {
       __Pyx_RaiseBufferIndexError(__pyx_t_4);
-      __PYX_ERR(0, 41, __pyx_L1_error)
+      __PYX_ERR(0, 65, __pyx_L1_error)
     }
     __pyx_t_1 = (((*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_array.data + __pyx_t_2 * __pyx_v_array.strides[0]) ) + __pyx_t_3 * __pyx_v_array.strides[1]) ))) < __pyx_v_key) != 0);
     if (__pyx_t_1) {
 
-      /* "graphframe_modules.pyx":42
- *       midpt = <long>floor((L+R)/2)
- *       if array[midpt][0] < key:
- *         L = midpt + 1             # <<<<<<<<<<<<<<
- *       elif array[midpt][0] > key:
- *         R = midpt - 1
+      /* "hatchet/cython_modules/graphframe_modules.pyx":66
+ *         midpt = <long>floor((L+R)/2)
+ *         if array[midpt][0] < key:
+ *             L = midpt + 1             # <<<<<<<<<<<<<<
+ *         elif array[midpt][0] > key:
+ *             R = midpt - 1
  */
       __pyx_v_L = (__pyx_v_midpt + 1);
 
-      /* "graphframe_modules.pyx":41
- *     while(L <= R):
- *       midpt = <long>floor((L+R)/2)
- *       if array[midpt][0] < key:             # <<<<<<<<<<<<<<
- *         L = midpt + 1
- *       elif array[midpt][0] > key:
+      /* "hatchet/cython_modules/graphframe_modules.pyx":65
+ *     while (L <= R):
+ *         midpt = <long>floor((L+R)/2)
+ *         if array[midpt][0] < key:             # <<<<<<<<<<<<<<
+ *             L = midpt + 1
+ *         elif array[midpt][0] > key:
  */
       goto __pyx_L5;
     }
 
-    /* "graphframe_modules.pyx":43
- *       if array[midpt][0] < key:
- *         L = midpt + 1
- *       elif array[midpt][0] > key:             # <<<<<<<<<<<<<<
- *         R = midpt - 1
- *       else:
+    /* "hatchet/cython_modules/graphframe_modules.pyx":67
+ *         if array[midpt][0] < key:
+ *             L = midpt + 1
+ *         elif array[midpt][0] > key:             # <<<<<<<<<<<<<<
+ *             R = midpt - 1
+ *         else:
  */
-    __pyx_t_3 = __pyx_v_midpt;
-    __pyx_t_2 = 0;
+    __pyx_t_5 = __pyx_v_midpt;
+    __pyx_t_6 = 0;
     __pyx_t_4 = -1;
-    if (__pyx_t_3 < 0) {
-      __pyx_t_3 += __pyx_v_array.shape[0];
-      if (unlikely(__pyx_t_3 < 0)) __pyx_t_4 = 0;
-    } else if (unlikely(__pyx_t_3 >= __pyx_v_array.shape[0])) __pyx_t_4 = 0;
-    if (__pyx_t_2 < 0) {
-      __pyx_t_2 += __pyx_v_array.shape[1];
-      if (unlikely(__pyx_t_2 < 0)) __pyx_t_4 = 1;
-    } else if (unlikely(__pyx_t_2 >= __pyx_v_array.shape[1])) __pyx_t_4 = 1;
+    if (__pyx_t_5 < 0) {
+      __pyx_t_5 += __pyx_v_array.shape[0];
+      if (unlikely(__pyx_t_5 < 0)) __pyx_t_4 = 0;
+    } else if (unlikely(__pyx_t_5 >= __pyx_v_array.shape[0])) __pyx_t_4 = 0;
+    if (__pyx_t_6 < 0) {
+      __pyx_t_6 += __pyx_v_array.shape[1];
+      if (unlikely(__pyx_t_6 < 0)) __pyx_t_4 = 1;
+    } else if (unlikely(__pyx_t_6 >= __pyx_v_array.shape[1])) __pyx_t_4 = 1;
     if (unlikely(__pyx_t_4 != -1)) {
       __Pyx_RaiseBufferIndexError(__pyx_t_4);
-      __PYX_ERR(0, 43, __pyx_L1_error)
+      __PYX_ERR(0, 67, __pyx_L1_error)
     }
-    __pyx_t_1 = (((*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_array.data + __pyx_t_3 * __pyx_v_array.strides[0]) ) + __pyx_t_2 * __pyx_v_array.strides[1]) ))) > __pyx_v_key) != 0);
+    __pyx_t_1 = (((*((unsigned PY_LONG_LONG const  *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_array.data + __pyx_t_5 * __pyx_v_array.strides[0]) ) + __pyx_t_6 * __pyx_v_array.strides[1]) ))) > __pyx_v_key) != 0);
     if (__pyx_t_1) {
 
-      /* "graphframe_modules.pyx":44
- *         L = midpt + 1
- *       elif array[midpt][0] > key:
- *         R = midpt - 1             # <<<<<<<<<<<<<<
- *       else:
- *         return midpt
+      /* "hatchet/cython_modules/graphframe_modules.pyx":68
+ *             L = midpt + 1
+ *         elif array[midpt][0] > key:
+ *             R = midpt - 1             # <<<<<<<<<<<<<<
+ *         else:
+ *             return midpt
  */
       __pyx_v_R = (__pyx_v_midpt - 1);
 
-      /* "graphframe_modules.pyx":43
- *       if array[midpt][0] < key:
- *         L = midpt + 1
- *       elif array[midpt][0] > key:             # <<<<<<<<<<<<<<
- *         R = midpt - 1
- *       else:
+      /* "hatchet/cython_modules/graphframe_modules.pyx":67
+ *         if array[midpt][0] < key:
+ *             L = midpt + 1
+ *         elif array[midpt][0] > key:             # <<<<<<<<<<<<<<
+ *             R = midpt - 1
+ *         else:
  */
       goto __pyx_L5;
     }
 
-    /* "graphframe_modules.pyx":46
- *         R = midpt - 1
- *       else:
- *         return midpt             # <<<<<<<<<<<<<<
+    /* "hatchet/cython_modules/graphframe_modules.pyx":70
+ *             R = midpt - 1
+ *         else:
+ *             return midpt             # <<<<<<<<<<<<<<
  *     return -1
  */
     /*else*/ {
       __Pyx_XDECREF(__pyx_r);
-      __pyx_t_5 = __Pyx_PyInt_From_long(__pyx_v_midpt); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 46, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __pyx_r = __pyx_t_5;
-      __pyx_t_5 = 0;
+      __pyx_t_7 = __Pyx_PyInt_From_long(__pyx_v_midpt); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 70, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __pyx_r = __pyx_t_7;
+      __pyx_t_7 = 0;
       goto __pyx_L0;
     }
     __pyx_L5:;
   }
 
-  /* "graphframe_modules.pyx":47
- *       else:
- *         return midpt
+  /* "hatchet/cython_modules/graphframe_modules.pyx":71
+ *         else:
+ *             return midpt
  *     return -1             # <<<<<<<<<<<<<<
  */
   __Pyx_XDECREF(__pyx_r);
@@ -2869,18 +2839,18 @@ static PyObject *__pyx_f_18graphframe_modules_binary_search(__Pyx_memviewslice _
   __pyx_r = __pyx_int_neg_1;
   goto __pyx_L0;
 
-  /* "graphframe_modules.pyx":34
+  /* "hatchet/cython_modules/graphframe_modules.pyx":52
+ *     return result
  * 
- * # basic binary search algorithm
  * cdef binary_search(const unsigned long long[:,:] array, const long arr_len, const unsigned long long key):             # <<<<<<<<<<<<<<
- *     # This search returns the index of key if found, -1 if not found
- *     cdef long L = 0
+ *     """Basic Binary Search.
+ * 
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("graphframe_modules.binary_search", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("hatchet.cython_modules.graphframe_modules.binary_search", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -2904,9 +2874,6 @@ static int __pyx_array___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, P
   PyObject *__pyx_v_format = 0;
   PyObject *__pyx_v_mode = 0;
   int __pyx_v_allocate_buffer;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
@@ -3045,9 +3012,6 @@ static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __
   Py_ssize_t __pyx_t_9;
   PyObject *__pyx_t_10 = NULL;
   Py_ssize_t __pyx_t_11;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__cinit__", 0);
   __Pyx_INCREF(__pyx_v_format);
 
@@ -3671,9 +3635,6 @@ static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(stru
   Py_ssize_t __pyx_t_5;
   int __pyx_t_6;
   Py_ssize_t *__pyx_t_7;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   if (__pyx_v_info == NULL) {
     PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete");
     return -1;
@@ -4102,9 +4063,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_5array_7memview___get__(struct _
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":223
@@ -4155,9 +4113,6 @@ static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *__pyx_v_self) {
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_memview", 0);
 
   /* "View.MemoryView":227
@@ -4296,9 +4251,6 @@ static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getattr__", 0);
 
   /* "View.MemoryView":234
@@ -4364,9 +4316,6 @@ static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
   /* "View.MemoryView":237
@@ -4431,9 +4380,6 @@ static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(struc
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setitem__", 0);
 
   /* "View.MemoryView":240
@@ -4491,9 +4437,6 @@ static PyObject *__pyx_pf___pyx_array___reduce_cython__(CYTHON_UNUSED struct __p
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
   /* "(tree fragment)":2
@@ -4548,9 +4491,6 @@ static PyObject *__pyx_pf___pyx_array_2__setstate_cython__(CYTHON_UNUSED struct
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":4
@@ -4598,9 +4538,6 @@ static struct __pyx_array_obj *__pyx_array_new(PyObject *__pyx_v_shape, Py_ssize
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("array_cwrapper", 0);
 
   /* "View.MemoryView":248
@@ -4768,9 +4705,6 @@ static struct __pyx_array_obj *__pyx_array_new(PyObject *__pyx_v_shape, Py_ssize
 static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_name = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
@@ -4932,9 +4866,6 @@ static PyObject *__pyx_pf___pyx_MemviewEnum___reduce_cython__(struct __pyx_Memvi
   int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
   /* "(tree fragment)":5
@@ -5160,9 +5091,6 @@ static PyObject *__pyx_pf___pyx_MemviewEnum_2__setstate_cython__(struct __pyx_Me
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":17
@@ -5292,9 +5220,6 @@ static int __pyx_memoryview___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_ar
   PyObject *__pyx_v_obj = 0;
   int __pyx_v_flags;
   int __pyx_v_dtype_is_object;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
@@ -5375,9 +5300,6 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit_
   int __pyx_t_2;
   int __pyx_t_3;
   int __pyx_t_4;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
   /* "View.MemoryView":346
@@ -5909,9 +5831,6 @@ static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__py
   PyObject *__pyx_t_5 = NULL;
   Py_ssize_t __pyx_t_6;
   char *__pyx_t_7;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_item_pointer", 0);
 
   /* "View.MemoryView":395
@@ -6059,9 +5978,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4_
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   char *__pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
   /* "View.MemoryView":404
@@ -6245,9 +6161,6 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setit
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setitem__", 0);
   __Pyx_INCREF(__pyx_v_index);
 
@@ -6463,9 +6376,6 @@ static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
   int __pyx_t_9;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("is_slice", 0);
   __Pyx_INCREF(__pyx_v_obj);
 
@@ -6672,9 +6582,6 @@ static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryvi
   int __pyx_t_4;
   int __pyx_t_5;
   int __pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("setitem_slice_assignment", 0);
 
   /* "View.MemoryView":445
@@ -6771,9 +6678,6 @@ static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memor
   PyObject *__pyx_t_10 = NULL;
   PyObject *__pyx_t_11 = NULL;
   PyObject *__pyx_t_12 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("setitem_slice_assign_scalar", 0);
 
   /* "View.MemoryView":451
@@ -7047,9 +6951,6 @@ static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *_
   __Pyx_RefNannyDeclarations
   char *__pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("setitem_indexed", 0);
 
   /* "View.MemoryView":482
@@ -7119,9 +7020,6 @@ static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview
   PyObject *__pyx_t_9 = NULL;
   size_t __pyx_t_10;
   int __pyx_t_11;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("convert_item_to_object", 0);
 
   /* "View.MemoryView":488
@@ -7400,9 +7298,6 @@ static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryvie
   char *__pyx_t_12;
   char *__pyx_t_13;
   char *__pyx_t_14;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("assign_item_from_object", 0);
 
   /* "View.MemoryView":504
@@ -7642,9 +7537,6 @@ static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbu
   void *__pyx_t_6;
   int __pyx_t_7;
   Py_ssize_t __pyx_t_8;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   if (__pyx_v_info == NULL) {
     PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete");
     return -1;
@@ -7981,9 +7873,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct _
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   int __pyx_t_2;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":554
@@ -8123,9 +8012,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(stru
   Py_ssize_t *__pyx_t_3;
   Py_ssize_t *__pyx_t_4;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":564
@@ -8205,9 +8091,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(st
   Py_ssize_t *__pyx_t_4;
   Py_ssize_t *__pyx_t_5;
   PyObject *__pyx_t_6 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":568
@@ -8319,9 +8202,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get_
   Py_ssize_t *__pyx_t_4;
   Py_ssize_t *__pyx_t_5;
   Py_ssize_t *__pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":576
@@ -8431,9 +8311,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struc
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":583
@@ -8494,9 +8371,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(s
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":587
@@ -8559,9 +8433,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(str
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":591
@@ -8637,9 +8508,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struc
   Py_ssize_t *__pyx_t_4;
   Py_ssize_t *__pyx_t_5;
   PyObject *__pyx_t_6 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
 
   /* "View.MemoryView":595
@@ -8853,9 +8721,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
   /* "View.MemoryView":612
@@ -8954,9 +8819,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__str__", 0);
 
   /* "View.MemoryView":616
@@ -9035,9 +8897,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16
   __Pyx_RefNannyDeclarations
   __Pyx_memviewslice *__pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("is_c_contig", 0);
 
   /* "View.MemoryView":622
@@ -9111,9 +8970,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18
   __Pyx_RefNannyDeclarations
   __Pyx_memviewslice *__pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("is_f_contig", 0);
 
   /* "View.MemoryView":628
@@ -9187,9 +9043,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20
   __Pyx_RefNannyDeclarations
   __Pyx_memviewslice __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("copy", 0);
 
   /* "View.MemoryView":633
@@ -9282,9 +9135,6 @@ static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22
   __Pyx_RefNannyDeclarations
   __Pyx_memviewslice __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("copy_fortran", 0);
 
   /* "View.MemoryView":645
@@ -9371,9 +9221,6 @@ static PyObject *__pyx_pf___pyx_memoryview___reduce_cython__(CYTHON_UNUSED struc
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
   /* "(tree fragment)":2
@@ -9428,9 +9275,6 @@ static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED st
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":4
@@ -9476,9 +9320,6 @@ static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, in
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("memoryview_cwrapper", 0);
 
   /* "View.MemoryView":658
@@ -9620,9 +9461,6 @@ static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) {
   int __pyx_t_9;
   int __pyx_t_10;
   PyObject *__pyx_t_11 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("_unellipsify", 0);
 
   /* "View.MemoryView":671
@@ -10065,9 +9903,6 @@ static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __
   Py_ssize_t *__pyx_t_3;
   int __pyx_t_4;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("assert_direct_dimensions", 0);
 
   /* "View.MemoryView":701
@@ -10175,9 +10010,6 @@ static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_
   Py_ssize_t __pyx_t_10;
   int __pyx_t_11;
   Py_ssize_t __pyx_t_12;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("memview_slice", 0);
 
   /* "View.MemoryView":711
@@ -10731,9 +10563,6 @@ static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst,
   int __pyx_t_1;
   int __pyx_t_2;
   int __pyx_t_3;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
 
   /* "View.MemoryView":827
  *     cdef bint negative_step
@@ -11520,9 +11349,6 @@ static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, P
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("pybuffer_index", 0);
 
   /* "View.MemoryView":912
@@ -11833,9 +11659,6 @@ static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) {
   int __pyx_t_7;
   int __pyx_t_8;
   int __pyx_t_9;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
 
   /* "View.MemoryView":944
  * @cname('__pyx_memslice_transpose')
@@ -12040,9 +11863,6 @@ static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memor
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("convert_item_to_object", 0);
 
   /* "View.MemoryView":980
@@ -12127,9 +11947,6 @@ static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memo
   int __pyx_t_1;
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("assign_item_from_object", 0);
 
   /* "View.MemoryView":986
@@ -12272,9 +12089,6 @@ static PyObject *__pyx_pf___pyx_memoryviewslice___reduce_cython__(CYTHON_UNUSED
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
   /* "(tree fragment)":2
@@ -12329,9 +12143,6 @@ static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUS
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":4
@@ -12385,9 +12196,6 @@ static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewsl
   Py_ssize_t *__pyx_t_7;
   Py_ssize_t *__pyx_t_8;
   Py_ssize_t __pyx_t_9;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("memoryview_fromslice", 0);
 
   /* "View.MemoryView":1007
@@ -12763,9 +12571,6 @@ static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __p
   int __pyx_t_1;
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_slice_from_memview", 0);
 
   /* "View.MemoryView":1055
@@ -12990,9 +12795,6 @@ static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("memoryview_copy", 0);
 
   /* "View.MemoryView":1083
@@ -13055,9 +12857,6 @@ static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview
   PyObject *(*__pyx_t_3)(char *);
   int (*__pyx_t_4)(char *, PyObject *);
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("memoryview_copy_from_slice", 0);
 
   /* "View.MemoryView":1094
@@ -13900,9 +13699,6 @@ static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src,
   struct __pyx_memoryview_obj *__pyx_t_4;
   int __pyx_t_5;
   int __pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
 
   /* "View.MemoryView":1219
  *     cdef void *result
@@ -14150,9 +13946,6 @@ static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   #ifdef WITH_THREAD
   PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
   #endif
@@ -14238,9 +14031,6 @@ static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, char *__pyx_v_msg,
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   #ifdef WITH_THREAD
   PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
   #endif
@@ -14323,9 +14113,6 @@ static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) {
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   #ifdef WITH_THREAD
   PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
   #endif
@@ -14443,9 +14230,6 @@ static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_
   int __pyx_t_6;
   void *__pyx_t_7;
   int __pyx_t_8;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
 
   /* "View.MemoryView":1276
  *     Check for overlapping memory and verify the shapes.
@@ -15522,9 +15306,6 @@ static PyObject *__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum(PyObject *_
   PyObject *__pyx_v___pyx_type = 0;
   long __pyx_v___pyx_checksum;
   PyObject *__pyx_v___pyx_state = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__pyx_unpickle_Enum (wrapper)", 0);
@@ -15602,9 +15383,6 @@ static PyObject *__pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(CYTHON_UNUSE
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   int __pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__pyx_unpickle_Enum", 0);
 
   /* "(tree fragment)":4
@@ -15793,9 +15571,6 @@ static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *__
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__pyx_unpickle_Enum__set_state", 0);
 
   /* "(tree fragment)":12
@@ -15937,9 +15712,9 @@ static void __pyx_tp_dealloc_array(PyObject *o) {
   {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);
+    ++Py_REFCNT(o);
     __pyx_array___dealloc__(o);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);
+    --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
   }
   Py_CLEAR(p->mode);
@@ -16028,7 +15803,7 @@ static PyBufferProcs __pyx_tp_as_buffer_array = {
 
 static PyTypeObject __pyx_type___pyx_array = {
   PyVarObject_HEAD_INIT(0, 0)
-  "graphframe_modules.array", /*tp_name*/
+  "hatchet.cython_modules.graphframe_modules.array", /*tp_name*/
   sizeof(struct __pyx_array_obj), /*tp_basicsize*/
   0, /*tp_itemsize*/
   __pyx_tp_dealloc_array, /*tp_dealloc*/
@@ -16147,7 +15922,7 @@ static PyMethodDef __pyx_methods_Enum[] = {
 
 static PyTypeObject __pyx_type___pyx_MemviewEnum = {
   PyVarObject_HEAD_INIT(0, 0)
-  "graphframe_modules.Enum", /*tp_name*/
+  "hatchet.cython_modules.graphframe_modules.Enum", /*tp_name*/
   sizeof(struct __pyx_MemviewEnum_obj), /*tp_basicsize*/
   0, /*tp_itemsize*/
   __pyx_tp_dealloc_Enum, /*tp_dealloc*/
@@ -16248,9 +16023,9 @@ static void __pyx_tp_dealloc_memoryview(PyObject *o) {
   {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);
+    ++Py_REFCNT(o);
     __pyx_memoryview___dealloc__(o);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);
+    --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
   }
   Py_CLEAR(p->obj);
@@ -16408,7 +16183,7 @@ static PyBufferProcs __pyx_tp_as_buffer_memoryview = {
 
 static PyTypeObject __pyx_type___pyx_memoryview = {
   PyVarObject_HEAD_INIT(0, 0)
-  "graphframe_modules.memoryview", /*tp_name*/
+  "hatchet.cython_modules.graphframe_modules.memoryview", /*tp_name*/
   sizeof(struct __pyx_memoryview_obj), /*tp_basicsize*/
   0, /*tp_itemsize*/
   __pyx_tp_dealloc_memoryview, /*tp_dealloc*/
@@ -16498,9 +16273,9 @@ static void __pyx_tp_dealloc__memoryviewslice(PyObject *o) {
   {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);
+    ++Py_REFCNT(o);
     __pyx_memoryviewslice___dealloc__(o);
-    __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);
+    --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
   }
   Py_CLEAR(p->from_object);
@@ -16546,7 +16321,7 @@ static struct PyGetSetDef __pyx_getsets__memoryviewslice[] = {
 
 static PyTypeObject __pyx_type___pyx_memoryviewslice = {
   PyVarObject_HEAD_INIT(0, 0)
-  "graphframe_modules._memoryviewslice", /*tp_name*/
+  "hatchet.cython_modules.graphframe_modules._memoryviewslice", /*tp_name*/
   sizeof(struct __pyx_memoryviewslice_obj), /*tp_basicsize*/
   0, /*tp_itemsize*/
   __pyx_tp_dealloc__memoryviewslice, /*tp_dealloc*/
@@ -16622,7 +16397,7 @@ static PyTypeObject __pyx_type___pyx_memoryviewslice = {
 };
 
 static PyMethodDef __pyx_methods[] = {
-  {"fast_not_isin", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_18graphframe_modules_3fast_not_isin, METH_VARARGS|METH_KEYWORDS, 0},
+  {"fast_not_isin", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7hatchet_14cython_modules_18graphframe_modules_3fast_not_isin, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7hatchet_14cython_modules_18graphframe_modules_2fast_not_isin},
   {0, 0, 0, 0}
 };
 
@@ -16691,7 +16466,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_s_Unable_to_convert_item_to_object, __pyx_k_Unable_to_convert_item_to_object, sizeof(__pyx_k_Unable_to_convert_item_to_object), 0, 0, 1, 0},
   {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1},
   {&__pyx_n_s_View_MemoryView, __pyx_k_View_MemoryView, sizeof(__pyx_k_View_MemoryView), 0, 0, 1, 1},
-  {&__pyx_n_s_add_L, __pyx_k_add_L, sizeof(__pyx_k_add_L), 0, 0, 1, 1},
   {&__pyx_n_s_allocate_buffer, __pyx_k_allocate_buffer, sizeof(__pyx_k_allocate_buffer), 0, 0, 1, 1},
   {&__pyx_n_s_arr1, __pyx_k_arr1, sizeof(__pyx_k_arr1), 0, 0, 1, 1},
   {&__pyx_n_s_arr1_len, __pyx_k_arr1_len, sizeof(__pyx_k_arr1_len), 0, 0, 1, 1},
@@ -16717,11 +16491,12 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_u_fortran, __pyx_k_fortran, sizeof(__pyx_k_fortran), 0, 1, 0, 1},
   {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1},
   {&__pyx_kp_s_got_differing_extents_in_dimensi, __pyx_k_got_differing_extents_in_dimensi, sizeof(__pyx_k_got_differing_extents_in_dimensi), 0, 0, 1, 0},
-  {&__pyx_n_s_graphframe_modules, __pyx_k_graphframe_modules, sizeof(__pyx_k_graphframe_modules), 0, 0, 1, 1},
   {&__pyx_kp_s_graphframe_modules_pyx, __pyx_k_graphframe_modules_pyx, sizeof(__pyx_k_graphframe_modules_pyx), 0, 0, 1, 0},
+  {&__pyx_n_s_hatchet_cython_modules_graphfram, __pyx_k_hatchet_cython_modules_graphfram, sizeof(__pyx_k_hatchet_cython_modules_graphfram), 0, 0, 1, 1},
   {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1},
   {&__pyx_n_s_id, __pyx_k_id, sizeof(__pyx_k_id), 0, 0, 1, 1},
   {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1},
+  {&__pyx_n_s_insert_one_for_self_nodes, __pyx_k_insert_one_for_self_nodes, sizeof(__pyx_k_insert_one_for_self_nodes), 0, 0, 1, 1},
   {&__pyx_n_s_itemsize, __pyx_k_itemsize, sizeof(__pyx_k_itemsize), 0, 0, 1, 1},
   {&__pyx_kp_s_itemsize_0_for_cython_array, __pyx_k_itemsize_0_for_cython_array, sizeof(__pyx_k_itemsize_0_for_cython_array), 0, 0, 1, 0},
   {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
@@ -16773,7 +16548,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {0, 0, 0, 0, 0, 0, 0}
 };
 static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {
-  __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 8, __pyx_L1_error)
+  __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 15, __pyx_L1_error)
   __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 133, __pyx_L1_error)
   __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) __PYX_ERR(1, 148, __pyx_L1_error)
   __pyx_builtin_enumerate = __Pyx_GetBuiltinName(__pyx_n_s_enumerate); if (!__pyx_builtin_enumerate) __PYX_ERR(1, 151, __pyx_L1_error)
@@ -16982,17 +16757,17 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
   __Pyx_GOTREF(__pyx_tuple__18);
   __Pyx_GIVEREF(__pyx_tuple__18);
 
-  /* "graphframe_modules.pyx":7
- * 
+  /* "hatchet/cython_modules/graphframe_modules.pyx":13
+ * # Description: All cython code related to graphframe.py
  * @cython.boundscheck(False)
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ * def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):
- *       self_missing_node[snio_indices[i]] = 'L'
  */
-  __pyx_tuple__19 = PyTuple_Pack(4, __pyx_n_s_snio_len, __pyx_n_s_self_missing_node, __pyx_n_s_snio_indices, __pyx_n_s_i); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 7, __pyx_L1_error)
+  __pyx_tuple__19 = PyTuple_Pack(4, __pyx_n_s_snio_len, __pyx_n_s_self_missing_node, __pyx_n_s_snio_indices, __pyx_n_s_i); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 13, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_tuple__19);
   __Pyx_GIVEREF(__pyx_tuple__19);
-  __pyx_codeobj__20 = (PyObject*)__Pyx_PyCode_New(3, 0, 4, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__19, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_graphframe_modules_pyx, __pyx_n_s_add_L, 7, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__20)) __PYX_ERR(0, 7, __pyx_L1_error)
+  __pyx_codeobj__20 = (PyObject*)__Pyx_PyCode_New(3, 0, 4, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__19, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_graphframe_modules_pyx, __pyx_n_s_insert_one_for_self_nodes, 13, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__20)) __PYX_ERR(0, 13, __pyx_L1_error)
 
   /* "View.MemoryView":286
  *         return self.name
@@ -17115,9 +16890,6 @@ static int __Pyx_modinit_function_export_code(void) {
 
 static int __Pyx_modinit_type_init_code(void) {
   __Pyx_RefNannyDeclarations
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0);
   /*--- Type init code ---*/
   __pyx_vtabptr_array = &__pyx_vtable_array;
@@ -17203,19 +16975,17 @@ static int __Pyx_modinit_function_import_code(void) {
 }
 
 
-#ifndef CYTHON_NO_PYINIT_EXPORT
-#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC
-#elif PY_MAJOR_VERSION < 3
-#ifdef __cplusplus
-#define __Pyx_PyMODINIT_FUNC extern "C" void
-#else
+#if PY_MAJOR_VERSION < 3
+#ifdef CYTHON_NO_PYINIT_EXPORT
 #define __Pyx_PyMODINIT_FUNC void
-#endif
 #else
-#ifdef __cplusplus
-#define __Pyx_PyMODINIT_FUNC extern "C" PyObject *
+#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC
+#endif
 #else
+#ifdef CYTHON_NO_PYINIT_EXPORT
 #define __Pyx_PyMODINIT_FUNC PyObject *
+#else
+#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC
 #endif
 #endif
 
@@ -17298,9 +17068,6 @@ static CYTHON_SMALL_CODE int __pyx_pymod_exec_graphframe_modules(PyObject *__pyx
 {
   PyObject *__pyx_t_1 = NULL;
   static PyThread_type_lock __pyx_t_2[8];
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
   __Pyx_RefNannyDeclarations
   #if CYTHON_PEP489_MULTI_PHASE_INIT
   if (__pyx_m) {
@@ -17377,26 +17144,26 @@ if (!__Pyx_RefNanny) {
   #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
   if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   #endif
-  if (__pyx_module_is_main_graphframe_modules) {
+  if (__pyx_module_is_main_hatchet__cython_modules__graphframe_modules) {
     if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name_2, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   }
   #if PY_MAJOR_VERSION >= 3
   {
     PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error)
-    if (!PyDict_GetItemString(modules, "graphframe_modules")) {
-      if (unlikely(PyDict_SetItemString(modules, "graphframe_modules", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error)
+    if (!PyDict_GetItemString(modules, "hatchet.cython_modules.graphframe_modules")) {
+      if (unlikely(PyDict_SetItemString(modules, "hatchet.cython_modules.graphframe_modules", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error)
     }
   }
   #endif
   /*--- Builtin init code ---*/
-  if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error;
   /*--- Constants init code ---*/
-  if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error;
   /*--- Global type/function init code ---*/
   (void)__Pyx_modinit_global_init_code();
   (void)__Pyx_modinit_variable_export_code();
   (void)__Pyx_modinit_function_export_code();
-  if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error)
+  if (unlikely(__Pyx_modinit_type_init_code() != 0)) goto __pyx_L1_error;
   (void)__Pyx_modinit_type_import_code();
   (void)__Pyx_modinit_variable_import_code();
   (void)__Pyx_modinit_function_import_code();
@@ -17405,34 +17172,34 @@ if (!__Pyx_RefNanny) {
   if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   #endif
 
-  /* "graphframe_modules.pyx":3
- * # Description: All cython code related to graphframe.py
+  /* "hatchet/cython_modules/graphframe_modules.pyx":7
+ * 
  * import cython
  * import numpy as np             # <<<<<<<<<<<<<<
  * from libc.math cimport floor
  * 
  */
-  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "graphframe_modules.pyx":7
- * 
+  /* "hatchet/cython_modules/graphframe_modules.pyx":13
+ * # Description: All cython code related to graphframe.py
  * @cython.boundscheck(False)
- * def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ * def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):             # <<<<<<<<<<<<<<
+ *     """Adds a '1' where rows are in self but not in other."""
  *     for i in range(snio_len):
- *       self_missing_node[snio_indices[i]] = 'L'
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_18graphframe_modules_1add_L, NULL, __pyx_n_s_graphframe_modules); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7hatchet_14cython_modules_18graphframe_modules_1insert_one_for_self_nodes, NULL, __pyx_n_s_hatchet_cython_modules_graphfram); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_add_L, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_insert_one_for_self_nodes, __pyx_t_1) < 0) __PYX_ERR(0, 13, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "graphframe_modules.pyx":1
- * # Description: All cython code related to graphframe.py             # <<<<<<<<<<<<<<
- * import cython
- * import numpy as np
+  /* "hatchet/cython_modules/graphframe_modules.pyx":1
+ * # Copyright 2017-2020 Lawrence Livermore National Security, LLC and other             # <<<<<<<<<<<<<<
+ * # Hatchet Project Developers. See the top-level LICENSE file for details.
+ * #
  */
   __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
@@ -17599,11 +17366,11 @@ if (!__Pyx_RefNanny) {
   __Pyx_XDECREF(__pyx_t_1);
   if (__pyx_m) {
     if (__pyx_d) {
-      __Pyx_AddTraceback("init graphframe_modules", __pyx_clineno, __pyx_lineno, __pyx_filename);
+      __Pyx_AddTraceback("init hatchet.cython_modules.graphframe_modules", __pyx_clineno, __pyx_lineno, __pyx_filename);
     }
     Py_CLEAR(__pyx_m);
   } else if (!PyErr_Occurred()) {
-    PyErr_SetString(PyExc_ImportError, "init graphframe_modules");
+    PyErr_SetString(PyExc_ImportError, "init hatchet.cython_modules.graphframe_modules");
   }
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -17724,7 +17491,7 @@ static int __Pyx_ParseOptionalKeywords(
         }
         name = first_kw_arg;
         #if PY_MAJOR_VERSION < 3
-        if (likely(PyString_Check(key))) {
+        if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) {
             while (*name) {
                 if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key))
                         && _PyString_Eq(**name, key)) {
@@ -17751,7 +17518,7 @@ static int __Pyx_ParseOptionalKeywords(
             while (*name) {
                 int cmp = (**name == key) ? 0 :
                 #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
-                    (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
+                    (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 :
                 #endif
                     PyUnicode_Compare(**name, key);
                 if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
@@ -17767,7 +17534,7 @@ static int __Pyx_ParseOptionalKeywords(
                 while (argname != first_kw_arg) {
                     int cmp = (**argname == key) ? 0 :
                     #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
-                        (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 :
+                        (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 :
                     #endif
                         PyUnicode_Compare(**argname, key);
                     if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
@@ -17815,7 +17582,7 @@ __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview,
     int i, retval=-1;
     Py_buffer *buf = &memview->view;
     __Pyx_RefNannySetupContext("init_memviewslice", 0);
-    if (unlikely(memviewslice->memview || memviewslice->data)) {
+    if (memviewslice->memview || memviewslice->data) {
         PyErr_SetString(PyExc_ValueError,
             "memviewslice is already initialized!");
         goto fail;
@@ -17894,13 +17661,13 @@ __Pyx_INC_MEMVIEW(__Pyx_memviewslice *memslice, int have_gil, int lineno)
 {
     int first_time;
     struct __pyx_memoryview_obj *memview = memslice->memview;
-    if (unlikely(!memview || (PyObject *) memview == Py_None))
+    if (!memview || (PyObject *) memview == Py_None)
         return;
-    if (unlikely(__pyx_get_slice_count(memview) < 0))
+    if (__pyx_get_slice_count(memview) < 0)
         __pyx_fatalerror("Acquisition count is %d (line %d)",
                          __pyx_get_slice_count(memview), lineno);
     first_time = __pyx_add_acquisition_count(memview) == 0;
-    if (unlikely(first_time)) {
+    if (first_time) {
         if (have_gil) {
             Py_INCREF((PyObject *) memview);
         } else {
@@ -17914,16 +17681,18 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW(__Pyx_memviewslice *memslice,
                                              int have_gil, int lineno) {
     int last_time;
     struct __pyx_memoryview_obj *memview = memslice->memview;
-    if (unlikely(!memview || (PyObject *) memview == Py_None)) {
+    if (!memview ) {
+        return;
+    } else if ((PyObject *) memview == Py_None) {
         memslice->memview = NULL;
         return;
     }
-    if (unlikely(__pyx_get_slice_count(memview) <= 0))
+    if (__pyx_get_slice_count(memview) <= 0)
         __pyx_fatalerror("Acquisition count is %d (line %d)",
                          __pyx_get_slice_count(memview), lineno);
     last_time = __pyx_sub_acquisition_count(memview) == 1;
     memslice->data = NULL;
-    if (unlikely(last_time)) {
+    if (last_time) {
         if (have_gil) {
             Py_CLEAR(memslice->memview);
         } else {
@@ -18828,9 +18597,9 @@ static CYTHON_INLINE PyObject* __Pyx_decode_c_string(
         if (stop < 0)
             stop += length;
     }
-    if (unlikely(stop <= start))
-        return PyUnicode_FromUnicode(NULL, 0);
     length = stop - start;
+    if (unlikely(length <= 0))
+        return PyUnicode_FromUnicode(NULL, 0);
     cstring += start;
     if (decode_func) {
         return decode_func(cstring, length, errors);
@@ -19105,7 +18874,7 @@ static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
     {
         #if PY_MAJOR_VERSION >= 3
         if (level == -1) {
-            if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) {
+            if (strchr(__Pyx_MODULE_NAME, '.')) {
                 module = PyImport_ImportModuleLevelObject(
                     name, global_dict, empty_dict, list, 1);
                 if (!module) {
@@ -19464,28 +19233,6 @@ bad:
     return -1;
 }
 
-/* PyObjectGetAttrStrNoError */
-static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) {
-    __Pyx_PyThreadState_declare
-    __Pyx_PyThreadState_assign
-    if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
-        __Pyx_PyErr_Clear();
-}
-static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) {
-    PyObject *result;
-#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1
-    PyTypeObject* tp = Py_TYPE(obj);
-    if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) {
-        return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1);
-    }
-#endif
-    result = __Pyx_PyObject_GetAttrStr(obj, attr_name);
-    if (unlikely(!result)) {
-        __Pyx_PyObject_GetAttrStr_ClearAttributeError();
-    }
-    return result;
-}
-
 /* SetupReduce */
 static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
   int ret;
@@ -19531,23 +19278,15 @@ static int __Pyx_setup_reduce(PyObject* type_obj) {
 #endif
         reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD;
         if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) {
-            reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython);
-            if (likely(reduce_cython)) {
-                ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
-                ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
-            } else if (reduce == object_reduce || PyErr_Occurred()) {
-                goto __PYX_BAD;
-            }
+            reduce_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_cython); if (unlikely(!reduce_cython)) goto __PYX_BAD;
+            ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
+            ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
             setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate);
             if (!setstate) PyErr_Clear();
             if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) {
-                setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython);
-                if (likely(setstate_cython)) {
-                    ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
-                    ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
-                } else if (!setstate || PyErr_Occurred()) {
-                    goto __PYX_BAD;
-                }
+                setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate_cython); if (unlikely(!setstate_cython)) goto __PYX_BAD;
+                ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
+                ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD;
             }
             PyType_Modified((PyTypeObject*)type_obj);
         }
@@ -20230,7 +19969,9 @@ static PyObject *
 __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
 {
     const char *ts = *tsp;
-    int i = 0, number, ndim;
+    int i = 0, number;
+    int ndim = ctx->head->field->type->ndim;
+;
     ++ts;
     if (ctx->new_count != 1) {
         PyErr_SetString(PyExc_ValueError,
@@ -20238,7 +19979,6 @@ __pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
         return NULL;
     }
     if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
-    ndim = ctx->head->field->type->ndim;
     while (*ts && *ts != ')') {
         switch (*ts) {
             case ' ': case '\f': case '\r': case '\n': case '\t': case '\v':  continue;
@@ -20368,8 +20108,8 @@ static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const cha
       case 'l': case 'L': case 'q': case 'Q':
       case 'f': case 'd': case 'g':
       case 'O': case 'p':
-        if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) &&
-            (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) {
+        if (ctx->enc_type == *ts && got_Z == ctx->is_complex &&
+            ctx->enc_packmode == ctx->new_packmode) {
           ctx->enc_count += ctx->new_count;
           ctx->new_count = 1;
           got_Z = 0;
@@ -20455,13 +20195,13 @@ __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec)
     if (buf->strides) {
         if (spec & __Pyx_MEMVIEW_CONTIG) {
             if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) {
-                if (unlikely(buf->strides[dim] != sizeof(void *))) {
+                if (buf->strides[dim] != sizeof(void *)) {
                     PyErr_Format(PyExc_ValueError,
                                  "Buffer is not indirectly contiguous "
                                  "in dimension %d.", dim);
                     goto fail;
                 }
-            } else if (unlikely(buf->strides[dim] != buf->itemsize)) {
+            } else if (buf->strides[dim] != buf->itemsize) {
                 PyErr_SetString(PyExc_ValueError,
                                 "Buffer and memoryview are not contiguous "
                                 "in the same dimension.");
@@ -20472,7 +20212,7 @@ __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec)
             Py_ssize_t stride = buf->strides[dim];
             if (stride < 0)
                 stride = -stride;
-            if (unlikely(stride < buf->itemsize)) {
+            if (stride < buf->itemsize) {
                 PyErr_SetString(PyExc_ValueError,
                                 "Buffer and memoryview are not contiguous "
                                 "in the same dimension.");
@@ -20480,17 +20220,17 @@ __pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec)
             }
         }
     } else {
-        if (unlikely(spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1)) {
+        if (spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1) {
             PyErr_Format(PyExc_ValueError,
                          "C-contiguous buffer is not contiguous in "
                          "dimension %d", dim);
             goto fail;
-        } else if (unlikely(spec & (__Pyx_MEMVIEW_PTR))) {
+        } else if (spec & (__Pyx_MEMVIEW_PTR)) {
             PyErr_Format(PyExc_ValueError,
                          "C-contiguous buffer is not indirect in "
                          "dimension %d", dim);
             goto fail;
-        } else if (unlikely(buf->suboffsets)) {
+        } else if (buf->suboffsets) {
             PyErr_SetString(PyExc_ValueError,
                             "Buffer exposes suboffsets but no strides");
             goto fail;
@@ -20504,7 +20244,7 @@ static int
 __pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec)
 {
     if (spec & __Pyx_MEMVIEW_DIRECT) {
-        if (unlikely(buf->suboffsets && buf->suboffsets[dim] >= 0)) {
+        if (buf->suboffsets && buf->suboffsets[dim] >= 0) {
             PyErr_Format(PyExc_ValueError,
                          "Buffer not compatible with direct access "
                          "in dimension %d.", dim);
@@ -20512,7 +20252,7 @@ __pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec
         }
     }
     if (spec & __Pyx_MEMVIEW_PTR) {
-        if (unlikely(!buf->suboffsets || (buf->suboffsets[dim] < 0))) {
+        if (!buf->suboffsets || (buf->suboffsets[dim] < 0)) {
             PyErr_Format(PyExc_ValueError,
                          "Buffer is not indirectly accessible "
                          "in dimension %d.", dim);
@@ -20530,7 +20270,9 @@ __pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag)
     if (c_or_f_flag & __Pyx_IS_F_CONTIG) {
         Py_ssize_t stride = 1;
         for (i = 0; i < ndim; i++) {
-            if (unlikely(stride * buf->itemsize != buf->strides[i]  &&  buf->shape[i] > 1)) {
+            if (stride * buf->itemsize != buf->strides[i] &&
+                    buf->shape[i] > 1)
+            {
                 PyErr_SetString(PyExc_ValueError,
                     "Buffer not fortran contiguous.");
                 goto fail;
@@ -20540,7 +20282,8 @@ __pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag)
     } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) {
         Py_ssize_t stride = 1;
         for (i = ndim - 1; i >- 1; i--) {
-            if (unlikely(stride * buf->itemsize != buf->strides[i]  &&  buf->shape[i] > 1)) {
+            if (stride * buf->itemsize != buf->strides[i] &&
+                    buf->shape[i] > 1) {
                 PyErr_SetString(PyExc_ValueError,
                     "Buffer not C contiguous.");
                 goto fail;
@@ -20581,7 +20324,7 @@ static int __Pyx_ValidateAndInit_memviewslice(
             goto fail;
     }
     buf = &memview->view;
-    if (unlikely(buf->ndim != ndim)) {
+    if (buf->ndim != ndim) {
         PyErr_Format(PyExc_ValueError,
                 "Buffer has wrong number of dimensions (expected %d, got %d)",
                 ndim, buf->ndim);
@@ -20589,9 +20332,9 @@ static int __Pyx_ValidateAndInit_memviewslice(
     }
     if (new_memview) {
         __Pyx_BufFmt_Init(&ctx, stack, dtype);
-        if (unlikely(!__Pyx_BufFmt_CheckString(&ctx, buf->format))) goto fail;
+        if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
     }
-    if (unlikely((unsigned) buf->itemsize != dtype->size)) {
+    if ((unsigned) buf->itemsize != dtype->size) {
         PyErr_Format(PyExc_ValueError,
                      "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) "
                      "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)",
@@ -20604,12 +20347,12 @@ static int __Pyx_ValidateAndInit_memviewslice(
     }
     for (i = 0; i < ndim; i++) {
         spec = axes_specs[i];
-        if (unlikely(!__pyx_check_strides(buf, i, ndim, spec)))
+        if (!__pyx_check_strides(buf, i, ndim, spec))
             goto fail;
-        if (unlikely(!__pyx_check_suboffsets(buf, i, ndim, spec)))
+        if (!__pyx_check_suboffsets(buf, i, ndim, spec))
             goto fail;
     }
-    if (unlikely(buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag)))
+    if (buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag))
         goto fail;
     if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice,
                                          new_memview != NULL) == -1)) {
@@ -20626,7 +20369,7 @@ no_fail:
 }
 
 /* ObjectToMemviewSlice */
-  static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_char(PyObject *obj, int writable_flag) {
+  static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_short(PyObject *obj, int writable_flag) {
     __Pyx_memviewslice result = { 0, 0, { 0 }, { 0 }, { 0 } };
     __Pyx_BufFmt_StackElem stack[1];
     int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_STRIDED) };
@@ -20637,7 +20380,7 @@ no_fail:
     }
     retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, 0,
                                                  PyBUF_RECORDS_RO | writable_flag, 1,
-                                                 &__Pyx_TypeInfo_char, stack,
+                                                 &__Pyx_TypeInfo_short, stack,
                                                  &result, obj);
     if (unlikely(retcode == -1))
         goto __pyx_fail;
@@ -20779,7 +20522,7 @@ __pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs,
     struct __pyx_memoryview_obj *memview_obj = NULL;
     __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0);
     for (i = 0; i < ndim; i++) {
-        if (unlikely(from_mvs->suboffsets[i] >= 0)) {
+        if (from_mvs->suboffsets[i] >= 0) {
             PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with "
                                            "indirect dimensions (axis %d)", i);
             goto fail;
diff --git a/hatchet/cython_modules/graphframe_modules.pyx b/hatchet/cython_modules/graphframe_modules.pyx
index bd28bd6..b343c8f 100644
--- a/hatchet/cython_modules/graphframe_modules.pyx
+++ b/hatchet/cython_modules/graphframe_modules.pyx
@@ -10,10 +10,10 @@ from libc.math cimport floor
 
 # Description: All cython code related to graphframe.py
 @cython.boundscheck(False)
-def add_L(const long snio_len, char[:] self_missing_node, const long[:] snio_indices):
-    """Adds 'L' chars where rows are in self but not in other."""
+def insert_one_for_self_nodes(const long snio_len, short[:] self_missing_node, const long[:] snio_indices):
+    """Adds a '1' where rows are in self but not in other."""
     for i in range(snio_len):
-        self_missing_node[snio_indices[i]] = 'L'
+        self_missing_node[snio_indices[i]] = 1
 
 cpdef fast_not_isin(const unsigned long long[:,:] arr1, const unsigned long long[:,:] arr2, const long arr1_len, const long arr2_len):
     """Check if elements in arr1 exist in arr2.
diff --git a/hatchet/external/console.py b/hatchet/external/console.py
index 2624e75..b2cf838 100644
--- a/hatchet/external/console.py
+++ b/hatchet/external/console.py
@@ -182,15 +182,16 @@ class ConsoleRenderer:
                 self._ansi_color_for_name(node_name) + node_name + self.colors.end
             )
 
+            # 0 is "", 1 is "L", and 2 is "R"
             if "_missing_node" in dataframe.columns:
                 left_or_right = dataframe.loc[df_index, "_missing_node"]
-                if left_or_right == "":
+                if left_or_right == 0:
                     lr_decorator = ""
-                elif left_or_right == "L":
+                elif left_or_right == 1:
                     lr_decorator = u" {c.left}{decorator}{c.end}".format(
                         decorator=self.lr_arrows["◀"], c=self.colors
                     )
-                elif left_or_right == "R":
+                elif left_or_right == 2:
                     lr_decorator = u" {c.right}{decorator}{c.end}".format(
                         decorator=self.lr_arrows["▶"], c=self.colors
                     )
diff --git a/hatchet/graphframe.py b/hatchet/graphframe.py
index fabf18f..083ce58 100644
--- a/hatchet/graphframe.py
+++ b/hatchet/graphframe.py
@@ -830,18 +830,18 @@ class GraphFrame:
         # called _missing_node
         if not self_not_in_other.empty:
             self.dataframe = self.dataframe.assign(
-                _missing_node=np.zeros(len(self.dataframe), dtype=np.ubyte)
+                _missing_node=np.zeros(len(self.dataframe), dtype=np.short)
             )
         if not other_not_in_self.empty:
-            # initialize with R to save filling in later
+            # initialize with 2 to save filling in later
             other_not_in_self = other_not_in_self.assign(
-                _missing_node=["R" for x in range(len(other_not_in_self))]
+                _missing_node=[int(2) for x in range(len(other_not_in_self))]
             )
 
             # add a new column to self if other has nodes not in self
             if self_not_in_other.empty:
                 self.dataframe["_missing_node"] = np.zeros(
-                    len(self.dataframe), dtype=np.ubyte
+                    len(self.dataframe), dtype=np.short
                 )
 
         # get lengths to pass into
@@ -853,11 +853,11 @@ class GraphFrame:
             self_missing_node = self.dataframe["_missing_node"].values
             snio_indices = self_not_in_other.index.values
 
-            # This function adds "L" to all nodes in self.dataframe['_missing_node'] which
-            # are in self but not in the other graphframe & convert from bytes to chars
-            _gfm_cy.add_L(snio_len, self_missing_node, snio_indices)
+            # This function adds 1 to all nodes in self.dataframe['_missing_node'] which
+            # are in self but not in the other graphframe
+            _gfm_cy.insert_one_for_self_nodes(snio_len, self_missing_node, snio_indices)
             self.dataframe["_missing_node"] = np.array(
-                [chr(n) for n in self_missing_node]
+                [n for n in self_missing_node], dtype=np.short
             )
 
         # for nodes that only exist in other, set the metric to be nan (since
diff --git a/hatchet/query_matcher.py b/hatchet/query_matcher.py
index c45ebce..1b7a86d 100644
--- a/hatchet/query_matcher.py
+++ b/hatchet/query_matcher.py
@@ -3,9 +3,12 @@
 #
 # SPDX-License-Identifier: MIT
 
+from itertools import groupby
 from numbers import Real
 import re
+import pandas as pd
 from pandas import DataFrame
+from pandas.core.indexes.multi import MultiIndex
 
 from .node import Node, traversal_order
 
@@ -42,6 +45,36 @@ class QueryMatcher:
                 def filter_series(df_row):
                     matches = True
                     for k, v in attr_filter.items():
+                        if k == "depth":
+                            node = df_row.name
+                            if isinstance(v, str) and v.lower().startswith(compops):
+                                matches = matches and eval(
+                                    "{} {}".format(node._depth, v)
+                                )
+                            elif isinstance(v, Real):
+                                matches = matches and (node._depth == v)
+                            else:
+                                raise InvalidQueryFilter(
+                                    "Attribute {} has a numeric type. Valid filters for this attribute are a string starting with a comparison operator or a real number.".format(
+                                        k
+                                    )
+                                )
+                            continue
+                        if k == "node_id":
+                            node = df_row.name
+                            if isinstance(v, str) and v.lower().startswith(compops):
+                                matches = matches and eval(
+                                    "{} {}".format(node._hatchet_nid, v)
+                                )
+                            elif isinstance(v, Real):
+                                matches = matches and (node._hatchet_nid == v)
+                            else:
+                                raise InvalidQueryFilter(
+                                    "Attribute {} has a numeric type. Valid filters for this attribute are a string starting with a comparison operator or a real number.".format(
+                                        k
+                                    )
+                                )
+                            continue
                         if k not in df_row.keys():
                             return False
                         if isinstance(df_row[k], str):
@@ -94,7 +127,36 @@ class QueryMatcher:
                         )
                         first_no_drop_indices["val"] = False
                     matches = True
+                    node = df_row.name.to_frame().index[0][0]
                     for k, v in attr_filter.items():
+                        if k == "depth":
+                            if isinstance(v, str) and v.lower().startswith(compops):
+                                matches = matches and eval(
+                                    "{} {}".format(node._depth, v)
+                                )
+                            elif isinstance(v, Real):
+                                matches = matches and (node._depth == v)
+                            else:
+                                raise InvalidQueryFilter(
+                                    "Attribute {} has a numeric type. Valid filters for this attribute are a string starting with a comparison operator or a real number.".format(
+                                        k
+                                    )
+                                )
+                            continue
+                        if k == "node_id":
+                            if isinstance(v, str) and v.lower().startswith(compops):
+                                matches = matches and eval(
+                                    "{} {}".format(node._hatchet_nid, v)
+                                )
+                            elif isinstance(v, Real):
+                                matches = matches and (node._hatchet_nid == v)
+                            else:
+                                raise InvalidQueryFilter(
+                                    "Attribute {} has a numeric type. Valid filters for this attribute are a string starting with a comparison operator or a real number.".format(
+                                        k
+                                    )
+                                )
+                            continue
                         if k not in df_row.columns:
                             return False
                         if df_row[k].apply(type).eq(str).all():
@@ -232,7 +294,12 @@ class QueryMatcher:
         # query nodes the current node matches.
         for i, node_query in enumerate(self.query_pattern):
             _, filter_func = node_query
-            if filter_func(gf.dataframe.loc[node]):
+            row = None
+            if isinstance(gf.dataframe.index, MultiIndex):
+                row = pd.concat([gf.dataframe.loc[node]], keys=[node], names=["node"])
+            else:
+                row = gf.dataframe.loc[node]
+            if filter_func(row):
                 matches.append(i)
         self.search_cache[node._hatchet_nid] = matches
 
@@ -406,6 +473,7 @@ class QueryMatcher:
                 for s in sub_match:
                     if s is not None:
                         new_matches.append(m + s)
+                new_matches = [uniq_match for uniq_match, _ in groupby(new_matches)]
             # Overwrite the old matches with the updated matches
             matches = new_matches
             # If all the existing partial matches were not able to be


Test patch:
diff --git a/hatchet/tests/conftest.py b/hatchet/tests/conftest.py
index f917097..ffbbf55 100644
--- a/hatchet/tests/conftest.py
+++ b/hatchet/tests/conftest.py
@@ -494,7 +494,7 @@ def small_mock2():
                 {
                     "name": "B",
                     "type": "function",
-                    "metrics": {"time (inc)": 20.0, "time": 5.0},
+                    "metrics": {"time (inc)": 20.0, "time": 0.0},
                     "children": [
                         {
                             "name": "C",
diff --git a/hatchet/tests/graphframe.py b/hatchet/tests/graphframe.py
index 0cf483e..67e644e 100644
--- a/hatchet/tests/graphframe.py
+++ b/hatchet/tests/graphframe.py
@@ -5,6 +5,8 @@
 #
 # SPDX-License-Identifier: MIT
 
+from __future__ import division
+
 import pytest
 
 import numpy as np
@@ -707,9 +709,11 @@ def test_sub_decorator(small_mock1, small_mock2, small_mock3):
     gf4 = gf1 - gf2
 
     assert len(gf4.graph) == 8
-    assert gf4.dataframe.loc[gf4.dataframe["_missing_node"] == "R"].shape[0] == 2
-    assert gf4.dataframe.loc[gf4.dataframe["_missing_node"] == "L"].shape[0] == 1
-    assert gf4.dataframe.loc[gf4.dataframe["_missing_node"] == ""].shape[0] == 5
+    assert gf4.dataframe.loc[gf4.dataframe["_missing_node"] == 2].shape[0] == 2  # "R"
+    assert gf4.dataframe.loc[gf4.dataframe["_missing_node"] == 1].shape[0] == 1  # "L"
+    assert (
+        gf4.dataframe.loc[gf4.dataframe["_missing_node"] == 0].shape[0] == 5
+    )  # "" or same in both
 
     output = ConsoleRenderer(unicode=True, color=False).render(
         gf4.graph.roots,
@@ -735,9 +739,9 @@ def test_sub_decorator(small_mock1, small_mock2, small_mock3):
     assert len(gf3.graph) == 4
 
     assert len(gf5.graph) == 6
-    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == "R"].shape[0] == 0
-    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == "L"].shape[0] == 2
-    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == ""].shape[0] == 4
+    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == 2].shape[0] == 0  # "R"
+    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == 1].shape[0] == 2  # "L"
+    assert gf5.dataframe.loc[gf5.dataframe["_missing_node"] == 0].shape[0] == 4  # ""
 
     output = ConsoleRenderer(unicode=True, color=False).render(
         gf5.graph.roots,
@@ -758,6 +762,40 @@ def test_sub_decorator(small_mock1, small_mock2, small_mock3):
     assert u"55.000 H ◀" in output
 
 
+def test_div_decorator(small_mock1, small_mock2):
+    gf1 = GraphFrame.from_literal(small_mock1)
+    gf2 = GraphFrame.from_literal(small_mock2)
+
+    assert len(gf1.graph) == 6
+    assert len(gf2.graph) == 7
+
+    gf3 = gf1 / gf2
+
+    assert len(gf3.graph) == 8
+    assert gf3.dataframe.loc[gf3.dataframe["_missing_node"] == 2].shape[0] == 2  # "R"
+    assert gf3.dataframe.loc[gf3.dataframe["_missing_node"] == 1].shape[0] == 1  # "L"
+    assert gf3.dataframe.loc[gf3.dataframe["_missing_node"] == 0].shape[0] == 5  # ""
+
+    output = ConsoleRenderer(unicode=True, color=False).render(
+        gf3.graph.roots,
+        gf3.dataframe,
+        metric_column="time",
+        precision=3,
+        name_column="name",
+        expand_name=False,
+        context_column="file",
+        rank=0,
+        thread=0,
+        depth=10000,
+        highlight_name=False,
+        invert_colormap=False,
+    )
+    assert "1.000 C" in output
+    assert "inf B" in output
+    assert u"nan D ▶" in output
+    assert u"10.000 H ◀" in output
+
+
 def test_groupby_aggregate_simple(mock_dag_literal_module):
     r"""Test reindex on a simple graph:
 
diff --git a/hatchet/tests/query.py b/hatchet/tests/query.py
index 02e48c4..d89bf23 100644
--- a/hatchet/tests/query.py
+++ b/hatchet/tests/query.py
@@ -495,3 +495,110 @@ def test_apply_indices(calc_pi_hpct_db):
 
     gf.drop_index_levels()
     assert query.apply(gf) == matches
+
+
+def test_high_level_depth(mock_graph_literal):
+    gf = GraphFrame.from_literal(mock_graph_literal)
+    query = QueryMatcher([("*", {"depth": 1})])
+    roots = gf.graph.roots
+    matches = [[c] for r in roots for c in r.children]
+    assert query.apply(gf) == matches
+
+    query = QueryMatcher([("*", {"depth": "<= 2"})])
+    matches = [
+        [roots[0], roots[0].children[0], roots[0].children[0].children[0]],
+        [roots[0].children[0], roots[0].children[0].children[0]],
+        [roots[0].children[0].children[0]],
+        [roots[0], roots[0].children[0], roots[0].children[0].children[1]],
+        [roots[0].children[0], roots[0].children[0].children[1]],
+        [roots[0].children[0].children[1]],
+        [roots[0], roots[0].children[1], roots[0].children[1].children[0]],
+        [roots[0].children[1], roots[0].children[1].children[0]],
+        [roots[0].children[1].children[0]],
+        [roots[0], roots[0].children[2], roots[0].children[2].children[0]],
+        [roots[0].children[2], roots[0].children[2].children[0]],
+        [roots[0].children[2].children[0]],
+        [roots[0], roots[0].children[2], roots[0].children[2].children[1]],
+        [roots[0].children[2], roots[0].children[2].children[1]],
+        [roots[0].children[2].children[1]],
+        [roots[1], roots[1].children[0], roots[1].children[0].children[0]],
+        [roots[1].children[0], roots[1].children[0].children[0]],
+        [roots[1].children[0].children[0]],
+        [roots[1], roots[1].children[0], roots[1].children[0].children[1]],
+        [roots[1].children[0], roots[1].children[0].children[1]],
+        [roots[1].children[0].children[1]],
+    ]
+    assert sorted(query.apply(gf)) == sorted(matches)
+
+    with pytest.raises(InvalidQueryFilter):
+        query = QueryMatcher([{"depth": "hello"}])
+        query.apply(gf)
+
+
+def test_high_level_hatchet_nid(mock_graph_literal):
+    gf = GraphFrame.from_literal(mock_graph_literal)
+    query = QueryMatcher([("*", {"node_id": ">= 20"})])
+    root = gf.graph.roots[1]
+    matches = [
+        [root, root.children[0], root.children[0].children[0]],
+        [root.children[0], root.children[0].children[0]],
+        [root.children[0].children[0]],
+        [root, root.children[0], root.children[0].children[1]],
+        [root.children[0], root.children[0].children[1]],
+        [root.children[0].children[1]],
+    ]
+    assert sorted(query.apply(gf)) == sorted(matches)
+
+    query = QueryMatcher([{"node_id": 0}])
+    assert query.apply(gf) == [[gf.graph.roots[0]]]
+
+    with pytest.raises(InvalidQueryFilter):
+        query = QueryMatcher([{"node_id": "hello"}])
+        query.apply(gf)
+
+
+def test_high_level_depth_index_levels(calc_pi_hpct_db):
+    gf = GraphFrame.from_hpctoolkit(str(calc_pi_hpct_db))
+    root = gf.graph.roots[0]
+
+    query = QueryMatcher([("*", {"depth": "<= 2"})])
+    matches = [
+        [root, root.children[0], root.children[0].children[0]],
+        [root.children[0], root.children[0].children[0]],
+        [root.children[0].children[0]],
+        [root, root.children[0], root.children[0].children[1]],
+        [root.children[0], root.children[0].children[1]],
+        [root.children[0].children[1]],
+    ]
+    assert sorted(query.apply(gf)) == sorted(matches)
+
+    query = QueryMatcher([("*", {"depth": 0})])
+    matches = [[root]]
+    assert query.apply(gf) == matches
+
+    with pytest.raises(InvalidQueryFilter):
+        query = QueryMatcher([{"depth": "hello"}])
+        query.apply(gf)
+
+
+def test_high_level_node_id_index_levels(calc_pi_hpct_db):
+    gf = GraphFrame.from_hpctoolkit(str(calc_pi_hpct_db))
+    root = gf.graph.roots[0]
+
+    query = QueryMatcher([("*", {"node_id": "<= 2"})])
+    matches = [
+        [root, root.children[0]],
+        [root.children[0]],
+        [root, root.children[0], root.children[0].children[0]],
+        [root.children[0], root.children[0].children[0]],
+        [root.children[0].children[0]],
+    ]
+    assert sorted(query.apply(gf)) == sorted(matches)
+
+    query = QueryMatcher([("*", {"node_id": 0})])
+    matches = [[root]]
+    assert query.apply(gf) == matches
+
+    with pytest.raises(InvalidQueryFilter):
+        query = QueryMatcher([{"node_id": "hello"}])
+        query.apply(gf)