def readPrefs_dms_tools_format(f):
charmatch = re.compile('<STR_LIT>')<EOL>if isinstance(f, str):<EOL><INDENT>f = open(f)<EOL>lines = f.readlines()<EOL>f.close()<EOL><DEDENT>else:<EOL><INDENT>lines = f.readlines()<EOL><DEDENT>characters = []<EOL>sites = []<EOL>wts = {}<EOL>pi_means = {}<EOL>pi_95credint = {}<EOL>h = {}<EOL>for line in lines:<EOL><INDENT>if line.isspace():<EOL><INDENT>continue<EOL><DEDENT>elif line[<NUM_LIT:0>] == '<STR_LIT:#>' and not characters:<EOL><INDENT>entries = line[<NUM_LIT:1> : ].strip().split()<EOL>if len(entries) < <NUM_LIT:4>:<EOL><INDENT>raise ValueError("<STR_LIT>" % line)<EOL><DEDENT>if not (entries[<NUM_LIT:0>] in ['<STR_LIT>', '<STR_LIT>'] and entries[<NUM_LIT:1>][ : <NUM_LIT:2>] == '<STR_LIT>' and entries[<NUM_LIT:2>] == '<STR_LIT>'):<EOL><INDENT>raise ValueError("<STR_LIT>" % line)<EOL><DEDENT>i = <NUM_LIT:3><EOL>while i < len(entries) and charmatch.search(entries[i]):<EOL><INDENT>characters.append(charmatch.search(entries[i]).group(<NUM_LIT:1>))<EOL>i += <NUM_LIT:1><EOL><DEDENT>if i  == len(entries):<EOL><INDENT>pi_95credint = None<EOL>linelength = len(characters) + <NUM_LIT:3><EOL><DEDENT>else:<EOL><INDENT>if not len(entries) - i == len(characters):<EOL><INDENT>raise ValueError("<STR_LIT>" % line)<EOL><DEDENT>if not all([entries[i + j] == '<STR_LIT>' % characters[j] for j in range(len(characters))]):<EOL><INDENT>raise ValueError("<STR_LIT>" % line)<EOL><DEDENT>linelength = <NUM_LIT:2> * len(characters) + <NUM_LIT:3><EOL><DEDENT><DEDENT>elif line[<NUM_LIT:0>] == '<STR_LIT:#>':<EOL><INDENT>continue<EOL><DEDENT>elif not characters:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>entries = line.strip().split()<EOL>if len(entries) != linelength:<EOL><INDENT>raise ValueError("<STR_LIT>" % (linelength, line))<EOL><DEDENT>r = entries[<NUM_LIT:0>]<EOL>assert r not in sites, "<STR_LIT>" % r<EOL>sites.append(r)<EOL>wts[r] = entries[<NUM_LIT:1>]<EOL>assert entries[<NUM_LIT:1>] in characters or entries[<NUM_LIT:1>] == '<STR_LIT:?>', "<STR_LIT>" % (entries[<NUM_LIT:1>], '<STR_LIT:U+002CU+0020>'.join(characters))<EOL>h[r] = float(entries[<NUM_LIT:2>])<EOL>pi_means[r] = dict([(x, float(entries[<NUM_LIT:3> + i])) for (i, x) in enumerate(characters)])<EOL>if pi_95credint != None:<EOL><INDENT>pi_95credint[r] = dict([(x, (float(entries[<NUM_LIT:3> + len(characters) + i].split('<STR_LIT:U+002C>')[<NUM_LIT:0>]), float(entries[<NUM_LIT:3> + len(characters) + i].split('<STR_LIT:U+002C>')[<NUM_LIT:1>]))) for (i, x) in enumerate(characters)])<EOL><DEDENT><DEDENT><DEDENT>return (sites, wts, pi_means, pi_95credint, h)<EOL>
Reads the amino-acid preferences written by `dms_tools v1 <http://jbloomlab.github.io/dms_tools/>`_.

    This is an exact copy of the same code from
    `dms_tools.file_io.ReadPreferences`. It is copied because
    `dms_tools v1 <http://jbloomlab.github.io/dms_tools/>`_ is currently
    only compatible with `python2`, and we needed something that also works
    with `python3`.

    *f* is the name of an existing file or a readable file-like object.
    It should be in the format written by
    `dms_tools v1 <http://jbloomlab.github.io/dms_tools/>`_.

    The return value is the tuple: *(sites, wts, pi_means, pi_95credint, h)*
    where *sites*, *wts*, *pi_means*, and *pi_95credint* will all
    have the same values used to write the file with *WritePreferences*,
    and *h* is a dictionary with *h[r]* giving the site entropy (log base
    2) for each *r* in *sites*.