scripts/last-dotplot
changeset 906 21fbf377641f
parent 905 8d52cef22afa
child 907 87991b57ed04
     1.1 --- a/scripts/last-dotplot	Wed Nov 08 12:17:50 2017 +0900
     1.2 +++ b/scripts/last-dotplot	Wed Nov 08 13:46:08 2017 +0900
     1.3 @@ -11,6 +11,7 @@
     1.4  
     1.5  import gzip
     1.6  from fnmatch import fnmatchcase
     1.7 +from operator import itemgetter
     1.8  import subprocess
     1.9  import itertools, optparse, os, re, sys
    1.10  
    1.11 @@ -213,22 +214,22 @@
    1.12      '''Return miscellaneous information about the sequences.'''
    1.13      if sortOpt == 1:
    1.14          seqNames.sort(key=natural_sort_key)
    1.15 -    seqSizes = [seqLimits[i][1] - seqLimits[i][0] for i in seqNames]
    1.16 +    rangeSizes = [seqLimits[i][1] - seqLimits[i][0] for i in seqNames]
    1.17      for i in seqNames:
    1.18          r = seqLimits[i]
    1.19          out = i, str(r[0]), str(r[1])
    1.20          warn("\t".join(out))
    1.21      warn("")
    1.22      if sortOpt == 2:
    1.23 -        seqRecords = sorted(zip(seqSizes, seqNames), reverse=True)
    1.24 -        seqSizes = [i[0] for i in seqRecords]
    1.25 +        seqRecords = sorted(zip(rangeSizes, seqNames), reverse=True)
    1.26 +        rangeSizes = [i[0] for i in seqRecords]
    1.27          seqNames = [i[1] for i in seqRecords]
    1.28      seqRanges = [(i, seqLimits[i][0], seqLimits[i][1]) for i in seqNames]
    1.29      labelData = list(rangeLabels(seqRanges, labelOpt,
    1.30                                   font, fontsize, image_mode, textRot))
    1.31      margin = max(i[2] for i in labelData)
    1.32      # xxx the margin may be too big, because some labels may get omitted
    1.33 -    return seqNames, seqSizes, labelData, margin
    1.34 +    return seqRanges, rangeSizes, labelData, margin
    1.35  
    1.36  def div_ceil(x, y):
    1.37      '''Return x / y rounded up.'''
    1.38 @@ -488,12 +489,16 @@
    1.39          draw.text(position, i[3], font=font, fill=opts.text_color)
    1.40      return im
    1.41  
    1.42 -def rangesPerSeq(seqNames, seqLimits, rangePixBegs, bpPerPix):
    1.43 -    for i, j in zip(seqNames, rangePixBegs):
    1.44 -        beg, end = seqLimits[i]
    1.45 -        origin = bpPerPix * j - beg
    1.46 -        r = beg, end, origin
    1.47 -        yield i, [r]
    1.48 +def rangesWithOrigins(sortedRanges, rangePixBegs, bpPerPix):
    1.49 +    for i, j in zip(sortedRanges, rangePixBegs):
    1.50 +        seqName, rangeBeg, rangeEnd = i
    1.51 +        origin = bpPerPix * j - rangeBeg
    1.52 +        yield seqName, (rangeBeg, rangeEnd, origin)
    1.53 +
    1.54 +def rangesPerSeq(sortedRanges, rangePixBegs, bpPerPix):
    1.55 +    a = rangesWithOrigins(sortedRanges, rangePixBegs, bpPerPix)
    1.56 +    for k, v in itertools.groupby(a, itemgetter(0)):
    1.57 +        yield k, [i[1] for i in v]
    1.58  
    1.59  def getFont(opts):
    1.60      if opts.fontfile:
    1.61 @@ -533,12 +538,12 @@
    1.62      textRot1 = "vertical".startswith(opts.rot1)
    1.63      i1 = getSeqInfo(opts.sort1, seqNames1, seqLimits1,
    1.64                      font, opts.fontsize, image_mode, opts.labels1, textRot1)
    1.65 -    seqNames1, rangeSizes1, labelData1, tMargin = i1
    1.66 +    sortedRanges1, rangeSizes1, labelData1, tMargin = i1
    1.67  
    1.68      textRot2 = "horizontal".startswith(opts.rot2)
    1.69      i2 = getSeqInfo(opts.sort2, seqNames2, seqLimits2,
    1.70                      font, opts.fontsize, image_mode, opts.labels2, textRot2)
    1.71 -    seqNames2, rangeSizes2, labelData2, lMargin = i2
    1.72 +    sortedRanges2, rangeSizes2, labelData2, lMargin = i2
    1.73  
    1.74      maxPixels1 = opts.width  - lMargin
    1.75      maxPixels2 = opts.height - tMargin
    1.76 @@ -549,13 +554,11 @@
    1.77  
    1.78      p1 = pixelData(rangeSizes1, bpPerPix, opts.border_pixels, lMargin)
    1.79      rangePixBegs1, rangePixLens1, width = p1
    1.80 -    rangeDict1 = dict(rangesPerSeq(seqNames1, seqLimits1, rangePixBegs1,
    1.81 -                                   bpPerPix))
    1.82 +    rangeDict1 = dict(rangesPerSeq(sortedRanges1, rangePixBegs1, bpPerPix))
    1.83  
    1.84      p2 = pixelData(rangeSizes2, bpPerPix, opts.border_pixels, tMargin)
    1.85      rangePixBegs2, rangePixLens2, height = p2
    1.86 -    rangeDict2 = dict(rangesPerSeq(seqNames2, seqLimits2, rangePixBegs2,
    1.87 -                                   bpPerPix))
    1.88 +    rangeDict2 = dict(rangesPerSeq(sortedRanges2, rangePixBegs2, bpPerPix))
    1.89  
    1.90      warn("width:  " + str(width))
    1.91      warn("height: " + str(height))