def LogoPlot(sites, datatype, data, plotfile, nperline,<EOL>numberevery=<NUM_LIT:10>, allowunsorted=False, ydatamax=<NUM_LIT>,<EOL>overlay=None, fix_limits={}, fixlongname=False,<EOL>overlay_cmap=None, ylimits=None, relativestackheight=<NUM_LIT:1>,<EOL>custom_cmap='<STR_LIT>', map_metric='<STR_LIT>', noseparator=False,<EOL>underlay=False, scalebar=False):
assert datatype in ['<STR_LIT>', '<STR_LIT>', '<STR_LIT>'], "<STR_LIT>".format(datatype)<EOL>assert sites, "<STR_LIT>"<EOL>assert set(sites) == set(data.keys()), "<STR_LIT>"<EOL>characters = list(data[sites[<NUM_LIT:0>]].keys())<EOL>aas = sorted(AA_TO_INDEX.keys())<EOL>if set(characters) == set(NT_TO_INDEX.keys()):<EOL><INDENT>alphabet_type = '<STR_LIT>'<EOL><DEDENT>elif set(characters) == set(aas) or set(characters) == set(aas + ['<STR_LIT:*>']):<EOL><INDENT>alphabet_type = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>" % str(characters))<EOL><DEDENT>for r in sites:<EOL><INDENT>if set(data[r].keys()) != set(characters):<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT><DEDENT>firstblankchar = '<STR_LIT:B>' <EOL>assert firstblankchar not in characters, "<STR_LIT>"<EOL>lastblankchar = '<STR_LIT:b>' <EOL>assert lastblankchar not in characters, "<STR_LIT>"<EOL>separatorchar = '<STR_LIT:->' <EOL>assert separatorchar not in characters, "<STR_LIT>"<EOL>if noseparator:<EOL><INDENT>separatorheight = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>separatorheight = <NUM_LIT> <EOL><DEDENT>if os.path.splitext(plotfile)[<NUM_LIT:1>].lower() != '<STR_LIT>':<EOL><INDENT>raise ValueError("<STR_LIT>" % plotfile)<EOL><DEDENT>if os.path.isfile(plotfile):<EOL><INDENT>os.remove(plotfile) <EOL><DEDENT>if not allowunsorted:<EOL><INDENT>sorted_sites = natsort.natsorted([r for r in sites])<EOL>if sorted_sites != sites:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT><DEDENT>stackwidth = <NUM_LIT> <EOL>barheight = <NUM_LIT> <EOL>barspacing = <NUM_LIT> <EOL>stackaspectratio = <NUM_LIT> <EOL>assert relativestackheight > <NUM_LIT:0>, "<STR_LIT>"<EOL>stackaspectratio *= relativestackheight<EOL>if overlay:<EOL><INDENT>if len(overlay) > <NUM_LIT:3>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>ymax = (stackaspectratio * stackwidth + len(overlay) * (barspacing + barheight)) / float(stackaspectratio * stackwidth)<EOL>aspectratio = ymax * stackaspectratio <EOL><DEDENT>else:<EOL><INDENT>ymax = <NUM_LIT:1.0> <EOL>aspectratio = stackaspectratio<EOL><DEDENT>rmargin = <NUM_LIT> <EOL>stackheightmargin = <NUM_LIT:16> <EOL>showscalebar = False<EOL>try:<EOL><INDENT>(fd, transfacfile) = tempfile.mkstemp()<EOL>f = os.fdopen(fd, '<STR_LIT:w>')<EOL>ordered_alphabets = {} <EOL>if datatype == '<STR_LIT>':<EOL><INDENT>chars_for_string = characters<EOL>f.write('<STR_LIT>' % '<STR_LIT:U+0020>'.join(chars_for_string))<EOL>for (isite, r) in enumerate(sites):<EOL><INDENT>f.write('<STR_LIT>' % (isite, '<STR_LIT:U+0020>'.join([str(data[r][x]) for x in characters])))<EOL>pi_r = [(data[r][x], x) for x in characters]<EOL>pi_r.sort()<EOL>ordered_alphabets[isite] = [tup[<NUM_LIT:1>] for tup in pi_r] <EOL><DEDENT><DEDENT>elif datatype == '<STR_LIT>':<EOL><INDENT>chars_for_string = characters + [firstblankchar, lastblankchar, separatorchar]<EOL>ydatamax *= <NUM_LIT> <EOL>f.write('<STR_LIT>' % '<STR_LIT:U+0020>'.join(chars_for_string))<EOL>for (isite, r) in enumerate(sites):<EOL><INDENT>positivesum = sum([data[r][x] for x in characters if data[r][x] > <NUM_LIT:0>]) + separatorheight / <NUM_LIT><EOL>negativesum = sum([data[r][x] for x in characters if data[r][x] < <NUM_LIT:0>]) - separatorheight / <NUM_LIT><EOL>if abs(positivesum + negativesum) > <NUM_LIT>:<EOL><INDENT>raise ValueError("<STR_LIT>" % (positivesum + negativesum, r))<EOL><DEDENT>if <NUM_LIT> * positivesum > ydatamax:<EOL><INDENT>raise ValueError("<STR_LIT>" % (ydatamax, <NUM_LIT> * positivesum))<EOL><DEDENT>f.write('<STR_LIT>' % isite)<EOL>deltapi_r = []<EOL>for x in characters:<EOL><INDENT>deltapi_r.append((data[r][x], x))<EOL>f.write('<STR_LIT>' % (abs(data[r][x]) / float(ydatamax)))<EOL><DEDENT>deltapi_r.sort()<EOL>firstpositiveindex = <NUM_LIT:0><EOL>while deltapi_r[firstpositiveindex][<NUM_LIT:0>] < <NUM_LIT:0>:<EOL><INDENT>firstpositiveindex += <NUM_LIT:1><EOL><DEDENT>ordered_alphabets[isite] = [firstblankchar] + [tup[<NUM_LIT:1>] for tup in deltapi_r[ : firstpositiveindex]] + [separatorchar] + [tup[<NUM_LIT:1>] for tup in deltapi_r[firstpositiveindex : ]] + [lastblankchar] <EOL>f.write('<STR_LIT>' % (<NUM_LIT:0.5> * (ydatamax + <NUM_LIT> * negativesum) / ydatamax, <NUM_LIT:0.5> * (ydatamax + <NUM_LIT> * negativesum) / ydatamax, separatorheight)) <EOL><DEDENT><DEDENT>elif datatype == '<STR_LIT>':<EOL><INDENT>assert ylimits, "<STR_LIT>"<EOL>(dataymin, dataymax) = ylimits<EOL>assert dataymax > <NUM_LIT:0> > dataymin, "<STR_LIT>".format(ylimits)<EOL>yextent = float(dataymax - dataymin)<EOL>separatorheight *= yextent<EOL>chars_for_string = characters + [firstblankchar, lastblankchar, separatorchar]<EOL>f.write('<STR_LIT>'.format('<STR_LIT:U+0020>'.join(chars_for_string)))<EOL>for (isite, r) in enumerate(sites):<EOL><INDENT>positivesum = sum([data[r][x] for x in characters if data[r][x] > <NUM_LIT:0>]) + separatorheight / <NUM_LIT><EOL>negativesum = sum([data[r][x] for x in characters if data[r][x] < <NUM_LIT:0>]) - separatorheight / <NUM_LIT><EOL>assert positivesum <= dataymax, "<STR_LIT>"<EOL>assert negativesum >= dataymin, "<STR_LIT>"<EOL>f.write('<STR_LIT>'.format(isite))<EOL>diffsel_r = []<EOL>for x in characters:<EOL><INDENT>diffsel_r.append((data[r][x], x))<EOL>f.write('<STR_LIT>'.format(abs(data[r][x]) / yextent))<EOL><DEDENT>diffsel_r.sort()<EOL>firstpositiveindex = <NUM_LIT:0><EOL>while diffsel_r[firstpositiveindex][<NUM_LIT:0>] < <NUM_LIT:0>:<EOL><INDENT>firstpositiveindex += <NUM_LIT:1><EOL><DEDENT>ordered_alphabets[isite] = [firstblankchar] + [tup[<NUM_LIT:1>] for tup in diffsel_r[ : firstpositiveindex]] + [separatorchar] + [tup[<NUM_LIT:1>] for tup in diffsel_r[firstpositiveindex : ]] + [lastblankchar] <EOL>f.write('<STR_LIT>' % ((negativesum - dataymin) / yextent, (dataymax - positivesum) / yextent, separatorheight / yextent)) <EOL><DEDENT>heightofone = stackwidth * stackaspectratio / yextent<EOL>assert heightofone > <NUM_LIT:0><EOL>if scalebar:<EOL><INDENT>showscalebar = (heightofone * scalebar[<NUM_LIT:0>], scalebar[<NUM_LIT:1>])<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>" % datatype)<EOL><DEDENT>f.close()<EOL>charstring = '<STR_LIT>'.join(chars_for_string)<EOL>assert len(charstring) == len(chars_for_string), "<STR_LIT>" % (str(chars_for_string))<EOL>logoprior = weblogolib.parse_prior('<STR_LIT>', charstring, <NUM_LIT:0>)<EOL>motif = _my_Motif.read_transfac(open(transfacfile), charstring)<EOL>logodata = weblogolib.LogoData.from_counts(motif.alphabet, motif, logoprior)<EOL>logo_options = weblogolib.LogoOptions()<EOL>logo_options.fineprint = None<EOL>logo_options.stacks_per_line = nperline<EOL>logo_options.stack_aspect_ratio = aspectratio<EOL>logo_options.stack_width = stackwidth<EOL>logo_options.unit_name = '<STR_LIT>'<EOL>logo_options.show_yaxis = False<EOL>logo_options.yaxis_scale = ymax <EOL>if alphabet_type == '<STR_LIT>':<EOL><INDENT>map_functions = {'<STR_LIT>':KyteDoolittleColorMapping,<EOL>'<STR_LIT>': MWColorMapping,<EOL>'<STR_LIT>' : ChargeColorMapping,<EOL>'<STR_LIT>':FunctionalGroupColorMapping}<EOL>map_fcn = map_functions[map_metric]<EOL>(cmap, colormapping, mapper) = map_fcn(maptype=custom_cmap)<EOL><DEDENT>elif alphabet_type == '<STR_LIT>':<EOL><INDENT>colormapping = {}<EOL>colormapping['<STR_LIT:A>'] = '<STR_LIT>'<EOL>colormapping['<STR_LIT:T>'] = '<STR_LIT>'<EOL>colormapping['<STR_LIT:C>'] = '<STR_LIT>'<EOL>colormapping['<STR_LIT>'] = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>raise ValueError("<STR_LIT>" % alphabet_type)<EOL><DEDENT>colormapping[firstblankchar] = colormapping[lastblankchar] = '<STR_LIT>' <EOL>colormapping[separatorchar] = '<STR_LIT>' <EOL>color_scheme = weblogolib.colorscheme.ColorScheme()<EOL>for x in chars_for_string:<EOL><INDENT>if hasattr(color_scheme, '<STR_LIT>'):<EOL><INDENT>color_scheme.rules.append(weblogolib.colorscheme.SymbolColor(x, colormapping[x], "<STR_LIT>" % x))<EOL><DEDENT>else:<EOL><INDENT>color_scheme.groups.append(weblogolib.colorscheme.ColorGroup(x, colormapping[x], "<STR_LIT>" % x))<EOL><DEDENT><DEDENT>logo_options.color_scheme = color_scheme<EOL>logo_options.annotate = [{True:r, False:'<STR_LIT>'}[<NUM_LIT:0> == isite % numberevery] for (isite, r) in enumerate(sites)]<EOL>logoformat = weblogolib.LogoFormat(logodata, logo_options)<EOL>pdf = _my_pdf_formatter(logodata, logoformat, ordered_alphabets) <EOL>with open(plotfile, '<STR_LIT:wb>') as f:<EOL><INDENT>f.write(pdf)<EOL><DEDENT>assert os.path.isfile(plotfile), "<STR_LIT>" % plotfile<EOL><DEDENT>finally:<EOL><INDENT>try:<EOL><INDENT>f.close()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>if os.path.isfile(transfacfile):<EOL><INDENT>os.remove(transfacfile)<EOL><DEDENT><DEDENT>if overlay or showscalebar:<EOL><INDENT>try:<EOL><INDENT>(fdoverlay, overlayfile) = tempfile.mkstemp(suffix='<STR_LIT>')<EOL>(fdmerged, mergedfile) = tempfile.mkstemp(suffix='<STR_LIT>')<EOL>foverlay = os.fdopen(fdoverlay, '<STR_LIT:wb>')<EOL>foverlay.close() <EOL>fmerged = os.fdopen(fdmerged, '<STR_LIT:wb>')<EOL>logoheight = stackwidth * stackaspectratio + stackheightmargin<EOL>LogoOverlay(sites, overlayfile, overlay, nperline, sitewidth=stackwidth, rmargin=rmargin, logoheight=logoheight, barheight=barheight, barspacing=barspacing, fix_limits=fix_limits, fixlongname=fixlongname, overlay_cmap=overlay_cmap, underlay=underlay, scalebar=showscalebar)<EOL>plotfile_f = open(plotfile, '<STR_LIT:rb>')<EOL>plot = PyPDF2.PdfFileReader(plotfile_f).getPage(<NUM_LIT:0>)<EOL>overlayfile_f = open(overlayfile, '<STR_LIT:rb>')<EOL>overlaypdf = PyPDF2.PdfFileReader(overlayfile_f).getPage(<NUM_LIT:0>)<EOL>xshift = overlaypdf.artBox[<NUM_LIT:2>] - plot.artBox[<NUM_LIT:2>]<EOL>yshift = (barheight + barspacing) * len(overlay) - <NUM_LIT:0.5> * barspacing<EOL>overlaypdf.mergeTranslatedPage(plot, xshift, <EOL>yshift * int(underlay), expand=True)<EOL>overlaypdf.compressContentStreams() <EOL>output = PyPDF2.PdfFileWriter()<EOL>output.addPage(overlaypdf)<EOL>output.write(fmerged)<EOL>fmerged.close()<EOL>shutil.move(mergedfile, plotfile)<EOL><DEDENT>finally:<EOL><INDENT>try:<EOL><INDENT>plotfile_f.close()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>overlayfile_f.close()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>foverlay.close()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>fmerged.close()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>for fname in [overlayfile, mergedfile]:<EOL><INDENT>if os.path.isfile(fname):<EOL><INDENT>os.remove(fname)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>
Create sequence logo showing amino-acid or nucleotide preferences.

    The heights of each letter is equal to the preference of
    that site for that amino acid or nucleotide.

    Note that stop codons may or may not be included in the logo
    depending on whether they are present in *pi_d*.  

    CALLING VARIABLES:

    * *sites* is a list of all of the sites that are being included
      in the logo, as strings. They must be in natural sort or an error
      will be raised **unless** *allowunsorted* is *True*. The sites
      in the plot are ordered in the same arrangement
      listed in *sites*. These should be **strings**, not integers.

    * *datatype* should be one of the following strings:

        * 'prefs' for preferences

        * 'diffprefs' for differential preferences

        * 'diffsel' for differential selection

    * *data* is a dictionary that has a key for every entry in
      *sites*. For every site *r* in *sites*, *sites[r][x]*
      is the value for character *x*. 
      Preferences must sum to one; differential preferences to zero.
      All sites must have the same set of characters. The characters
      must be the set of nucleotides or amino acids with or without
      stop codons.

    * *plotfile* is a string giving the name of the created PDF file 
      of the logo plot.
      It must end in the extension ``.pdf``.

    * *nperline* is the number of sites per line. Often 40 to 80 are good values.

    * *numberevery* is specifies how frequently we put labels for the sites on
      x-axis.

    * *allowunsorted* : if *True* then we allow the entries in *sites* to 
      **not** be sorted. This means that the logo plot will **not** have
      sites in sorted order.

    * *ydatamax* : meaningful only if *datatype* is 'diffprefs'. In this case, it gives
      the maximum that the logo stacks extend in the positive and negative directions.
      Cannot be smaller than the maximum extent of the differential preferences.

    * *ylimits*: is **mandatory** if *datatype* is 'diffsel', and meaningless 
      otherwise. It is *(ymin, ymax)* where *ymax > 0 > ymin*, and gives extent 
      of the data in the positive and negative directions. Must encompass the 
      actual maximum and minimum of the data.

    * *overlay* : make overlay bars that indicate other properties for
      the sites. If you set to something other than `None`, it should be
      a list giving one to three properties. Each property is a tuple:
      *(prop_d, shortname, longname)* where:

        - *prop_d* is a dictionary keyed by site numbers that are in *sites*.
          For each *r* in *sites*, *prop_d[r]* gives the value of the property,
          or if there is no entry in *prop_d* for *r*, then the property
          is undefined and is colored white. Properties can either be:

            * continuous: in this case, all of the values should be numbers.

            * discrete : in this case, all of the values should be strings.
              While in practice, if you have more than a few discrete
              categories (different strings), the plot will be a mess.

        - *shortname* : short name for the property; will not format well
          if more than 4 or 5 characters.

        - *longname* : longer name for property used on axes label. Can be the
          same as *shortname* if you don't need a different long name.

        - In the special case where both *shortname* and *longname* are 
          the string `wildtype`, then rather than an overlay bar we
          right the one-character wildtype identity in `prop_d` for each
          site.

    * *fix_limits* is only meaningful if *overlay* is being used. In this case, for any
      *shortname* in *overlay* that also keys an entry in *fix_limits*, we use
      *fix_limits[shortname]* to set the limits for *shortname*. Specifically,
      *fix_limits[shortname]* should be the 2-tuple *(ticks, ticknames)*. *ticks*
      should be a list of tick locations (numbers) and *ticknames* should be a list of
      the corresponding tick label for that tick.

    * If *fixlongname* is *True*, then we use the *longname* in *overlay* exactly as written;
      otherwise we add a parenthesis indicating the *shortname* for which this *longname*
      stands.

    * *overlay_cmap* can be the name of a valid *matplotlib.colors.Colormap*, such as the
      string *jet* or *bwr*. Otherwise, it can be *None* and a (hopefully) good choice will 
      be made for you.

    * *custom_cmap* can be the name of a valid *matplotlib.colors.Colormap* which will be
      used to color amino-acid one-letter codes in the logoplot by the *map_metric* when
      either 'kd' or 'mw' is used as *map_metric*.

    * *relativestackheight* indicates how high the letter stack is relative to
      the default. The default is multiplied by this number, so make it > 1
      for a higher letter stack.

    * *map_metric* specifies the amino-acid property metric used to map colors to amino-acid
      letters. Valid options are 'kd' (Kyte-Doolittle hydrophobicity scale, default), 'mw' 
      (molecular weight), 'functionalgroup' (functional groups: small, nucleophilic, hydrophobic,
      aromatic, basic, acidic, and amide), and 'charge' (charge at neutral pH). If 'charge' is used, then the
      argument for *custom_cmap* will no longer be meaningful, since 'charge' uses its own 
      blue/black/red colormapping. Similarly, 'functionalgroup' uses its own colormapping.

    * *noseparator* is only meaningful if *datatype* is 'diffsel' or 'diffprefs'.
      If it set to *True*, then we do **not** print a black horizontal line to
      separate positive and negative values.

    * *underlay* if `True` then make an underlay rather than an overlay.

    * *scalebar*: show a scale bar. If `False`, no scale bar shown. Otherwise
      should be a 2-tuple of `(scalebarlen, scalebarlabel)`. Currently only
      works when data is `diffsel`.