def concept_line_ok(start: int, max_len: int, category: str, cid: str) -> bool:
    """
    :param start:    start offset for this concept in article
    :param max_len:  length in characters of title + abstract
    :param category: concept category (Chemical, Disease, Gene, Species, etc.)
    :param cid:      concept id (MeSH id, NCBI gene or taxon id, etc.)
    :return:         True if this line should result in concept replacement;
                     False otherwise
    """
    # Some articles in pubtator offset file have concept replacement info for the
    # full text; we are only interested in the title and abstract.
    # Skip over any replacement of Species 9606 (human).
    # Skip over any DNAMutation or ProteinMutation concept replacement.
    # Skip over any replacement that has no useful concept id.
    return start < max_len and \
        not (category == 'Species' and cid == '9606') and \
        not ('Mutation' in category or cid == '' or cid == '-')