A function that will process either a split or join tree
            with reference to the other tree and store it as part of
            this CT instance.
            @ In, thisTree, a networkx.Graph instance representing a
                merge tree for which we will process all of its leaf
                nodes into this CT object
            @ In, thatTree, a networkx.Graph instance representing the
                opposing merge tree which will need to be updated as
                nodes from thisTree are processed
            @ Out, None

def _process_tree(self, thisTree, thatTree):
        """ A function that will process either a split or join tree
            with reference to the other tree and store it as part of
            this CT instance.
            @ In, thisTree, a networkx.Graph instance representing a
                merge tree for which we will process all of its leaf
                nodes into this CT object
            @ In, thatTree, a networkx.Graph instance representing the
                opposing merge tree which will need to be updated as
                nodes from thisTree are processed
            @ Out, None
        """
        if self.debug:
            sys.stdout.write("Processing Tree: ")
            start = time.clock()

        # Get all of the leaf nodes that are not branches in the other
        # tree
        if len(thisTree.nodes()) > 1:
            leaves = set(
                [
                    v
                    for v in thisTree.nodes()
                    if thisTree.in_degree(v) == 0 and thatTree.in_degree(v) < 2
                ]
            )
        else:
            leaves = set()

        while len(leaves) > 0:
            v = leaves.pop()

            # if self.debug:
            #     sys.stdout.write('\tProcessing {} -> {}\n'
            #                      .format(v, thisTree.edges(v)[0][1]))

            # Take the leaf and edge out of the input tree and place it
            # on the CT
            edges = list(thisTree.out_edges(v))
            if len(edges) != 1:
                warnings.warn(
                    "The node {} should have a single emanating "
                    "edge.\n".format(v)
                )
            e1 = edges[0][0]
            e2 = edges[0][1]
            # This may be a bit beside the point, but if we want all of
            # our edges pointing 'up,' we can verify that the edges we
            # add have the lower vertex pointing to the upper vertex.
            # This is useful only for nicely plotting with some graph
            # tools (graphviz/networkx), and I guess for consistency
            # sake.
            if self.Y[e1] < self.Y[e2]:
                self.edges.append((e1, e2))
            else:
                self.edges.append((e2, e1))

            # Removing the node will remove its constituent edges from
            # thisTree
            thisTree.remove_node(v)

            # This is the root node of the other tree
            if thatTree.out_degree(v) == 0:
                thatTree.remove_node(v)
                # if self.debug:
                #     sys.stdout.write('\t\tRemoving root {} from other tree\n'
                #                      .format(v))
            # This is a "regular" node in the other tree, suppress it
            # there, but be sure to glue the upper and lower portions
            # together
            else:
                # The other ends of the node being removed are added to
                # "that" tree

                if len(thatTree.in_edges(v)) > 0:
                    startNode = list(thatTree.in_edges(v))[0][0]
                else:
                    # This means we are at the root of the other tree,
                    # we can safely remove this node without connecting
                    # its predecessor with its descendant
                    startNode = None

                if len(thatTree.out_edges(v)) > 0:
                    endNode = list(thatTree.out_edges(v))[0][1]
                else:
                    # This means we are at a leaf of the other tree,
                    # we can safely remove this node without connecting
                    # its predecessor with its descendant
                    endNode = None

                if startNode is not None and endNode is not None:
                    thatTree.add_edge(startNode, endNode)

                thatTree.remove_node(v)

                # if self.debug:
                #     sys.stdout.write('\t\tSuppressing {} in other tree and '
                #                      'gluing {} to {}\n'
                #                      .format(v, startNode, endNode))

            if len(thisTree.nodes()) > 1:
                leaves = set(
                    [
                        v
                        for v in thisTree.nodes()
                        if thisTree.in_degree(v) == 0
                        and thatTree.in_degree(v) < 2
                    ]
                )
            else:
                leaves = set()

            # if self.debug:
            #     myMessage = '\t\tValid leaves: '
            #     sep = ''
            #     for leaf in leaves:
            #         myMessage += sep + str(leaf)
            #         sep = ','
            #     sys.stdout.write(myMessage+'\n')

        if self.debug:
            end = time.clock()
            sys.stdout.write("%f s\n" % (end - start))