Initialize a ``GenomeIntervalTree`` from a BED file.
        Each line of the file must consist of several fields, separated using ``field_sep``.
        The first three fields are ``chrom``, ``start`` and ``end`` (where ``start`` is 0-based and
        the corresponding interval is ``[start, end)``). The remaining fields are ``name``, ``score``,
        ``strand``, ..., or something else, depending on the flavor of the format.

        Each Interval in the tree has its data field set to a list with "remaining" fields,
        i.e. interval.data[0] should be the ``name``, interval.data[1] is the ``score``, etc.

        if the ``interval_maker`` parameter is not None, intervals are created by calling this function with the BED line split into fields as input.
        The function must return an iterable of ``Interval`` objects.

        Example::
            >>> test_url = 'http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeAwgTfbsUniform/wgEncodeAwgTfbsBroadDnd41Ezh239875UniPk.narrowPeak.gz'
            >>> data = zlib.decompress(urlopen(test_url).read(), 16+zlib.MAX_WBITS)
            >>> gtree = GenomeIntervalTree.from_bed(BytesIO(data))
            >>> len(gtree)
            1732
            >>> assert gtree[b'chr10'].search(22610878) == set([Interval(22610878, 22611813, [b'.', b'1000', b'.', b'471.725544438908', b'-1', b'3.21510858105313', b'389']), Interval(22610878, 22611813, [b'.', b'791', b'.', b'123.885507169449', b'-1', b'3.21510858105313', b'596'])])
            >>> assert gtree[b'chr10'].search(22611813) == set([])
            >>> assert gtree[b'chr1'].search(145036590, 145036594) == set([Interval(145036593, 145037123, [b'.', b'247', b'.', b'38.6720804428054', b'-1', b'3.06233123683911', b'265'])])
            >>> assert gtree[b'chr10'].search(145036594, 145036595) == set([])

def from_bed(fileobj, field_sep=b'\t', interval_maker=None):
        '''
        Initialize a ``GenomeIntervalTree`` from a BED file.
        Each line of the file must consist of several fields, separated using ``field_sep``.
        The first three fields are ``chrom``, ``start`` and ``end`` (where ``start`` is 0-based and
        the corresponding interval is ``[start, end)``). The remaining fields are ``name``, ``score``,
        ``strand``, ..., or something else, depending on the flavor of the format.

        Each Interval in the tree has its data field set to a list with "remaining" fields,
        i.e. interval.data[0] should be the ``name``, interval.data[1] is the ``score``, etc.

        if the ``interval_maker`` parameter is not None, intervals are created by calling this function with the BED line split into fields as input.
        The function must return an iterable of ``Interval`` objects.

        Example::
            >>> test_url = 'http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeAwgTfbsUniform/wgEncodeAwgTfbsBroadDnd41Ezh239875UniPk.narrowPeak.gz'
            >>> data = zlib.decompress(urlopen(test_url).read(), 16+zlib.MAX_WBITS)
            >>> gtree = GenomeIntervalTree.from_bed(BytesIO(data))
            >>> len(gtree)
            1732
            >>> assert gtree[b'chr10'].search(22610878) == set([Interval(22610878, 22611813, [b'.', b'1000', b'.', b'471.725544438908', b'-1', b'3.21510858105313', b'389']), Interval(22610878, 22611813, [b'.', b'791', b'.', b'123.885507169449', b'-1', b'3.21510858105313', b'596'])])
            >>> assert gtree[b'chr10'].search(22611813) == set([])
            >>> assert gtree[b'chr1'].search(145036590, 145036594) == set([Interval(145036593, 145037123, [b'.', b'247', b'.', b'38.6720804428054', b'-1', b'3.06233123683911', b'265'])])
            >>> assert gtree[b'chr10'].search(145036594, 145036595) == set([])

        '''
        # We collect all intervals into a set of lists, and then put them all at once into the tree structures
        # It is slightly more efficient than adding intervals one by one.
        # Moreover, the current implementation throws a "maximum recursion depth exceeded" error
        # in this case on large files (TODO)

        interval_lists = defaultdict(list)
        for ln in fileobj:
            if ln.endswith(b'\n'):
                ln = ln[0:-1]
            ln = ln.split(field_sep)
            if interval_maker is not None:
                for interval in interval_maker(ln):
                    interval_lists[ln[0]].append(_fix(interval))
            else:
                interval_lists[ln[0]].append(_fix(Interval(int(ln[1]), int(ln[2]), data=ln[3:])))
        gtree = GenomeIntervalTree()
        for k, v in getattr(interval_lists, 'iteritems', interval_lists.items)():
            gtree[k] = IntervalTree(v)
        return gtree