code: def bucketIterator(elements, buckets):
    def check_sorted(current, previous):
      if (previous is not None) and \
         ((previous.chrom > current.chrom) or
          ((previous.chrom == current.chrom) and
           (previous.start > current.start))):
        raise GenomicIntervalError("elements not sorted. Saw " +
                                   str(previous) + " before " + str(current))
    def updateOpen(openHeap, elementIterator, bucketChrom,
                   bucketStart, bucketEnd):
      while len(openHeap) > 0 and ((openHeap[0].chrom < bucketChrom) or
                                   ((openHeap[0].chrom == bucketChrom) and
                                   (openHeap[0].end <= bucketStart))):
        heappop(openHeap)
      while (elementIterator.peek() is not None) and \
            ((elementIterator.peek().chrom < bucketChrom) or
             ((elementIterator.peek().chrom == bucketChrom) and
              (elementIterator.peek().start < bucketEnd))):
        e = elementIterator.__next__()
        if (e.chrom < bucketChrom) or \
           (e.chrom == bucketChrom and e.end <= bucketStart):
           continue
        heappush(openHeap, e)
    openElems = []
    prevBucket = None
    elementIter = AutoApplyIterator(elements, check_sorted)
    for bucket in buckets:
      if prevBucket is not None and ((bucket.chrom < prevBucket.chrom) or
                                     (bucket.chrom == prevBucket.chrom and
                                      bucket.start < prevBucket.start)):
        raise GenomicIntervalError("regions-of-interest are not sorted. Saw " +
                                   str(prevBucket) + " before " + str(bucket))
      updateOpen(openElems, elementIter, bucket.chrom, bucket. start, bucket.end)
      yield bucket, [x for x in openElems if x.start < bucket.end]
      prevBucket = bucket