code: def chain_HSPs(blast, xdist=100, ydist=100):
      
      key = lambda x: (x.query, x.subject)
      blast.sort(key=key)
  
      clusters = Grouper()
      for qs, points in groupby(blast, key=key):
          points = sorted(list(points), \
                  key=lambda x: (x.qstart, x.qstop, x.sstart, x.sstop))
  
          n = len(points)
          for i in xrange(n):
              a = points[i]
              clusters.join(a)
              for j in xrange(i + 1, n):
                  b = points[j]
  
                  # x-axis distance
                  del_x = get_distance(a, b)
                  if del_x > xdist:
                      break
                  # y-axis distance
                  del_y = get_distance(a, b, xaxis=False)
                  if del_y > ydist:
                      continue
                  # otherwise join
                  clusters.join(a, b)
  
      chained_hsps = [combine_HSPs(x) for x in clusters]
      key = lambda x: (x.query, -x.score if x.has_score else 0)
      chained_hsps = sorted(chained_hsps, key=key)
  
      return chained_hsps
docs: Take a list of BlastLines (or a BlastSlow instance), and returns a list of
      BlastLines.