Create a string representation of a taxonomic hierarchy (QIIME for now).

    :type tax_lvl: dict
    :param tax_lvl: Keyed on the entries in ranks
    :type end: int
    :param end: The end rank index (0-based indexing). If end == 3
                then the returned string will contain K, P, C, and O.
    
    >>> tax_fmt({"K": "Bacteria", "P": "Firmicutes", "C": "Negativicutes", 
    ... "O": "Selenomonadales", "F": "Veillonellaceae", "G": "Veillonella", 
    ... "S": "Veillonella parvula", "SS": "Veillonella parvula DSM 2008"}, 4)
    'k__Bacteria; p__Firmicutes; c__Negativicutes; o__Selenomonadales'

def tax_fmt(tax_lvl, end):
    """
    Create a string representation of a taxonomic hierarchy (QIIME for now).

    :type tax_lvl: dict
    :param tax_lvl: Keyed on the entries in ranks
    :type end: int
    :param end: The end rank index (0-based indexing). If end == 3
                then the returned string will contain K, P, C, and O.
    
    >>> tax_fmt({"K": "Bacteria", "P": "Firmicutes", "C": "Negativicutes", 
    ... "O": "Selenomonadales", "F": "Veillonellaceae", "G": "Veillonella", 
    ... "S": "Veillonella parvula", "SS": "Veillonella parvula DSM 2008"}, 4)
    'k__Bacteria; p__Firmicutes; c__Negativicutes; o__Selenomonadales'
    """
    if "S" in tax_lvl:
        if "G" in tax_lvl and tax_lvl["S"].startswith(tax_lvl["G"]):
            tax_lvl["S"] = tax_lvl["S"][len(tax_lvl["G"])+1:]
    if "SS" in tax_lvl:
        if "S" in tax_lvl and tax_lvl["SS"].startswith(tax_lvl["S"]):
            tax_lvl["SS"] = tax_lvl["SS"][len(tax_lvl["S"])+1:]
    
    # print(ranks[:end])
    tax = ["{}__{}".format(r.lower(), tax_lvl[r] if r in tax_lvl else '') 
             for r in ranks[:end+1]]
    # add empty identifiers for ranks beyond end
    #TODO: remove the :-1 when SS support is added
    tax.extend(["{}__".format(r.lower()) for r in ranks[end+1:-1]])

    # even though Bacteria, Archea are now technically Domains/superkingdoms
    # GreenGenes and other databases still list the traditional 
    # kingdom/phylum/class/etc. So this is a hack to shoehorn the kraken-report
    # data into that format.
    if tax[0].startswith('d'):
        tax[0] = "k"+tax[0][1:]

    # print(tax)
    return tax