def expectedLabelPosition(peptide, labelStateInfo, sequence=None,
                          modPositions=None):
    """Returns a modification description of a certain label state of a peptide.

    :param peptide: Peptide sequence used to calculat the expected label state
        modifications
    :param labelStateInfo: An entry of :attr:`LabelDescriptor.labels` that
        describes a label state
    :param sequence: unmodified amino acid sequence of :var:`peptide`, if None
        it is generated by :func:`maspy.peptidemethods.removeModifications()`
    :param modPositions: dictionary describing the modification state of
        "peptide", if None it is generated by
        :func:`maspy.peptidemethods.returnModPositions()`

    :returns: {sequence position: sorted list of expected label modifications
                  on that position, ...
               }
    """
    if modPositions is None:
        modPositions = maspy.peptidemethods.returnModPositions(peptide,
                                                               indexStart=0
                                                               )
    if sequence is None:
        sequence = maspy.peptidemethods.removeModifications(peptide)

    currLabelMods = dict()
    for labelPosition, labelSymbols in viewitems(labelStateInfo['aminoAcidLabels']):
        labelSymbols = aux.toList(labelSymbols)
        if labelSymbols == ['']:
            pass
        elif labelPosition == 'nTerm':
            currLabelMods.setdefault(0, list())
            currLabelMods[0].extend(labelSymbols)
        else:
            for sequencePosition in aux.findAllSubstrings(sequence,
                                                          labelPosition):
                currLabelMods.setdefault(sequencePosition, list())
                currLabelMods[sequencePosition].extend(labelSymbols)

    if labelStateInfo['excludingModifications'] is not None:
        for excludingMod, excludedLabelSymbol in viewitems(labelStateInfo['excludingModifications']):
            if excludingMod not in modPositions:
                continue
            for excludingModPos in modPositions[excludingMod]:
                if excludingModPos not in currLabelMods:
                    continue
                if excludedLabelSymbol not in currLabelMods[excludingModPos]:
                    continue
                if len(currLabelMods[excludingModPos]) == 1:
                    del(currLabelMods[excludingModPos])
                else:
                    excludedModIndex = currLabelMods[excludingModPos].index(excludedLabelSymbol)
                    currLabelMods[excludingModPos].pop(excludedModIndex)

    for sequencePosition in list(viewkeys(currLabelMods)):
        currLabelMods[sequencePosition] = sorted(currLabelMods[sequencePosition])
    return currLabelMods
Returns a modification description of a certain label state of a peptide.

    :param peptide: Peptide sequence used to calculat the expected label state
        modifications
    :param labelStateInfo: An entry of :attr:`LabelDescriptor.labels` that
        describes a label state
    :param sequence: unmodified amino acid sequence of :var:`peptide`, if None
        it is generated by :func:`maspy.peptidemethods.removeModifications()`
    :param modPositions: dictionary describing the modification state of
        "peptide", if None it is generated by
        :func:`maspy.peptidemethods.returnModPositions()`

    :returns: {sequence position: sorted list of expected label modifications
                  on that position, ...
               }