Yield lines of bubble describing given BubbleTree
420523
def lines_from_tree(tree, nodes_and_set:bool=False) -> iter:
    """"""
    NODE = 'NODE\t{}'
    INCL = 'IN\t{}\t{}'
    EDGE = 'EDGE\t{}\t{}\t1.0'
    SET  = 'SET\t{}'

    if nodes_and_set:
        for node in tree.nodes():
            yield NODE.format(node)

        for node in tree.powernodes():
            yield SET.format(node)

    for node, includeds in tree.inclusions.items():
        for included in includeds:
            yield INCL.format(included, node)

    for node, succs in tree.edges.items():
        for succ in succs:
            yield EDGE.format(node, succ)
1298130
def readlines(self):
        
        continuation = False
        while True:
            yield self.readline(continuation)
            continuation = True
306410
def _iter_texts(self, tree):
        """"""
        skip = (
            not isinstance(tree, lxml.html.HtmlElement)  # comments, etc.
            or tree.tag in self.skipped_tags
        )
        if not skip:
            if tree.text:
                yield Text(tree.text, tree, 'text')
            for child in tree:
                for text in self._iter_texts(child):
                    yield text
        if tree.tail:
            yield Text(tree.tail, tree, 'tail')
908543
def get_lines(self, key):
        """"""
        if key in self._indices:
            return self._indices[key].values()
        else:
            return []
1285714
def from_list(commands):
    
    def subtrees(commands, level):
        if not commands:
            return

        acc = []
        parent, *commands = commands

        for command in commands:
            if command['level'] > level:
                acc.append(command)
            else:
                yield (parent, acc)
                parent = command
                acc.clear()
        yield (parent, acc)

    def walk(commands, level=0):
        return [
            {
                'description': key['description'],
                'children': walk(subtree, level + 1),
                'id': key['id']
            }
            for key, subtree in subtrees(commands, level)
        ]

    return walk(commands)
685205
def extract_tree_block(self):
        ""        

        lines = iter(self.data)
        while 1:
            try:
                line = next(lines).strip()
            except StopIteration:
                break
    
            # enter trees block
            if line.lower() == "begin trees;":
                while 1:
                    # iter through trees block
                    sub = next(lines).strip().split()
                    
                    # skip if a blank line
                    if not sub:
                        continue

                    # look for translation
                    if sub[0].lower() == "translate":
                        while sub[0] != ";":
                            sub = next(lines).strip().split()
                            self.tdict[sub[0]] = sub[-1].strip(",")

                    # parse tree blocks
                    if sub[0].lower().startswith("tree"):
                        self.newicks.append(sub[-1])
        
                    # end of trees block
                    if sub[0].lower() == "end;":
                        break
166307
def chunks(iterable, chunk):
    """"""
    for i in range(0, len(iterable), chunk):
        yield iterable[i:i + chunk]
404650
def tree_to_graph(bbltree:BubbleTree) -> Graph or Digraph:
    
    GraphObject = Digraph if bbltree.oriented else Graph
    def create(name:str):
        """Return a graphviz graph figurating a powernode"""
        ret = GraphObject('cluster_' + name)
        # dirty hack to get links between clusters: add a blank node inside
        # so the subgraph don't take it's name directly, but the blank node do.
        # ret.body.append('label = "{}"'.format(name))  # replaced by:
        ret.node(name, style='invis', shape='point')
        # ret.body.append('style=plaintext')
        ret.body.append('color=lightgrey')
        ret.body.append('label=""')
        ret.body.append('shape=ellipse')
        ret.body.append('penwidth=2')
        ret.body.append('pencolor=black')
        return ret
    nodes = frozenset(bbltree.nodes())
    subgraphs = {}
    # build for each powernode the associated subgraph, and add its successors
    for powernode in bbltree.powernodes():
        if powernode not in subgraphs:
            subgraphs[powernode] = create(powernode)
        for succ in bbltree.inclusions[powernode]:
            if succ not in subgraphs:
                if succ not in nodes:
                    subgraphs[succ] = create(succ)
                else:
                    subgraphs[powernode].node(succ)
    # add to Graph instances the Graph of successors as subgraphs 
    for powernode, succs in bbltree.inclusions.items():
        for succ in succs:
            if succ not in nodes:
                subgraphs[powernode].subgraph(subgraphs[succ])
    # build the final graph by adding to it subgraphs of roots
    graph = GraphObject('graph', graph_attr={'compound': 'true'})
    for root in bbltree.roots:
        if root in subgraphs:
            graph.subgraph(subgraphs[root])
    # add the edges to the final graph
    for source, targets in bbltree.edges.items():
        for target in targets:
            if source <= target:
                attrs = {}
                if source not in nodes:
                    attrs.update({'ltail': 'cluster_' + source})
                if target not in nodes:
                    attrs.update({'lhead': 'cluster_' + target})
                graph.edge(source, target, **attrs)
    # print(graph)  # debug line
    # graph.view()  # debug line
    return graph
916336
def tree2text(tree_obj, indent=4):
    # type: (TreeInfo, int) -> str
    
    parts = []

    def _format_node(node, depth=0):
        # type: (NodeInfo, int) -> None
        def p(*args):
            # type: (*str) -> None
            parts.append(" " * depth * indent)
            parts.extend(args)

        if node.is_leaf:
            value_repr = _format_leaf_value(tree_obj, node)
            parts.append("  ---> {}".format(value_repr))
        else:
            assert node.left is not None
            assert node.right is not None
            feat_name = node.feature_name

            if depth > 0:
                parts.append("\n")
            left_samples = node.left.sample_ratio
            p("{feat_name} <= {threshold:0.3f}  ({left_samples:0.1%})".format(
                left_samples=left_samples,
                feat_name=feat_name,
                threshold=node.threshold,
            ))
            _format_node(node.left, depth=depth + 1)

            parts.append("\n")
            right_samples = node.right.sample_ratio
            p("{feat_name} > {threshold:0.3f}  ({right_samples:0.1%})".format(
                right_samples=right_samples,
                feat_name=feat_name,
                threshold=node.threshold,
                ))
            _format_node(node.right, depth=depth + 1)

    _format_node(tree_obj.tree)
    return "".join(parts)
618338
def stretch(iterable, n=2):
    
    """
    times = range(n)
    for item in iterable:
        for i in times: yield item
604219
def do_tree(self, path, max_depth, level, full_path, include_stat):
        
        try:
            children = self.get_children(path)
        except (NoNodeError, NoAuthError):
            children = []

        for child in children:
            cpath = os.path.join(path, child) if full_path else child
            if include_stat:
                yield cpath, level, self.stat(os.path.join(path, child))
            else:
                yield cpath, level

            if max_depth == 0 or level + 1 < max_depth:
                cpath = os.path.join(path, child)
                for rchild_rlevel_rstat in self.do_tree(cpath, max_depth, level + 1, full_path, include_stat):
                    yield rchild_rlevel_rstat
327050
def grouper(iterable, n):
    ''''''
    args = [iter(iterable)] * n
    for group in izip_longest(fillvalue=None, *args):
        group = [g for g in group if g != None]
        yield group
433982
def _enum_lines(self):
        """"""
        with _open_table(self.path, self.encoding) as lines:
            for i, line in enumerate(lines):
                yield i, line
614778
def bbl_to_cys(bblfile:str, oriented:bool=False, width_as_cover:bool=True,
               show_cover:str='cover: {}', false_edge_on_hover:bool=True,
               default_poweredge_width:int=5):
    """"""
    # False edges in clique
    with open(bblfile) as fd:
        falsedges = tuple(
            (src, trg) for _, src, trg in
            (l.strip().split('\t') for l in fd if l.startswith('FALSEDGE'))
        )
    if false_edge_on_hover:
        nodes_in_false_edges = set(itertools.chain.from_iterable(falsedges))
    # Detect incomplete power edges
    with open(bblfile) as fd:
        falsepoweredges = {}
        for line in fd:
            if line.startswith('FALSEPOWEREDGE'):
                _, seta, setb, src, trg = line.strip().split('\t')
                falsepoweredges.setdefault(frozenset((seta, setb)), set()).add((src, trg))
                if false_edge_on_hover:
                    nodes_in_false_edges.add(src)
                    nodes_in_false_edges.add(trg)

    # Build node hierarchy
    tree = BubbleTree.from_bubble_file(bblfile, symmetric_edges=False, oriented=oriented)
    def isclique(node): return node in tree.edges.get(node, ())
    def handle_node(node, parent=None):
        clique = isclique(node)
        if false_edge_on_hover and clique:
            falsedges = ((src, trg) for src, trg in itertools.combinations(tuple(tree.nodes_in(node)), r=2)
                         if src in nodes_in_false_edges and trg in nodes_in_false_edges)
        else: falsedges = ()
        return JS_NODE_LINE(node, parent, clique=clique, falsedges=falsedges)

    yield from JS_HEADER

    for node in tree.roots:
        yield handle_node(node)
        yield JS_NODE_LINE(node, clique=isclique(node))
    parents = reversed_graph(tree.inclusions)  # (power)node -> direct parent
    for node, parents in parents.items():
        assert len(parents) == 1, {node: parents}
        yield handle_node(node, parent=next(iter(parents)))

    yield from JS_MIDDLE

    use_cover = width_as_cover or show_cover
    if use_cover:
        def coverof(source, target) -> int:
            source_cover = sum(1 for _ in tree.nodes_in(source))
            target_cover = sum(1 for _ in tree.nodes_in(target))
            return (source_cover or 1) * (target_cover or 1)
        def labelof(cover:int) -> str or None:
            if cover > 1:  # it's a power edge
                return show_cover.format(cover)
    # Now, (power) edges
    powernodes = frozenset(tree.powernodes())
    for source, targets in tree.edges.items():
        for target in targets:
            if target == source:  continue  # cliques are not handled this way
            label, attrs, isreflexive = None, {}, False
            ispower = source in powernodes or target in powernodes
            if use_cover:
                cover = coverof(source, target)
                label, attrs = labelof(cover), {'width': 2+cover if width_as_cover else default_poweredge_width}
            if ispower and frozenset((source, target)) in falsepoweredges:
                attrs['falsedges'] = list(map(list, falsepoweredges[frozenset((source, target))]))
            yield ' '*8 + JS_EDGE_LINE(source, target, ispower, label=label, attrs=attrs)

    # If asked so, add false edges in the file as regular edges
    if not false_edge_on_hover:
        for source, target in falsedges:
            yield ' '*8 + JS_FALSEDGE_LINE(source, target)
        for edges in falsepoweredges.values():
            for source, target in edges:
                yield ' '*8 + JS_FALSEDGE_LINE(source, target)

    yield from JS_FOOTER

    if false_edge_on_hover:
        yield from JS_MOUSEOVER_SHOW_CALLBACKS
    else:
        yield from JS_MOUSEOVER_WIDTH_CALLBACKS
432830
def rows(self):
        """"""
        for t in self.terms:

            for row in t.rows:
                term, value = row  # Value can either be a string, or a dict

                if isinstance(value, dict):  # Dict is for properties, which might be arg-children
                    term, args, remain = self._args(term, value)
                    yield term, args

                    # 'remain' is all of the children that didn't have an arg-child column -- the
                    # section didn't have a column heder for that ther.
                    for k, v in remain.items():
                        yield term.split('.')[-1] + '.' + k, v
                else:
                    yield row
834975
def _lines(self):
        

        chunkIndices = self._listChunks()
        for chunkIndex in chunkIndices:
            with self._openChunk(chunkIndex) as chunk:
                yield from chunk._lines()
771215
def _tree_line(self, no_type: bool = False) -> str:
        """"""
        keys = (" [" + " ".join([k[0] for k in self.keys]) + "]"
                if self.keys else "")
        return super()._tree_line() + keys