def clean_document(document,
                   sent_tokenize, _treebank_word_tokenize,
                   tagger,
                   lemmatizer,
                   lemmatize,
                   stopset,
                   first_cap_re, all_cap_re,
                   digits_punctuation_whitespace_re,
                   pos_set):
    """
    Extracts a clean bag-of-words from a document.

    Inputs: - document: A string containing some text.

    Output: - lemma_list: A python list of lemmas or stems.
            - lemma_to_keywordbag: A python dictionary that maps stems/lemmas to original topic keywords.
    """
    ####################################################################################################################
    # Tokenizing text
    ####################################################################################################################
    # start_time = time.perf_counter()
    try:
        tokenized_document = fast_word_tokenize(document, sent_tokenize, _treebank_word_tokenize)
    except LookupError:
        print("Warning: Could not tokenize document. If these warnings are commonplace, there is a problem with the nltk resources.")
        lemma_list = list()
        lemma_to_keywordbag = defaultdict(lambda: defaultdict(int))
        return lemma_list, lemma_to_keywordbag
    # elapsed_time = time.perf_counter() - start_time
    # print("Tokenize", elapsed_time)

    ####################################################################################################################
    # Separate ["camelCase"] into ["camel", "case"] and make every letter lower case
    ####################################################################################################################
    # start_time = time.perf_counter()
    tokenized_document = [separate_camel_case(token, first_cap_re, all_cap_re).lower() for token in tokenized_document]
    # elapsed_time = time.perf_counter() - start_time
    # print("camelCase", elapsed_time)

    ####################################################################################################################
    # Parts of speech tagger
    ####################################################################################################################
    # start_time = time.perf_counter()
    tokenized_document = tagger.tag(tokenized_document)
    tokenized_document = [token[0] for token in tokenized_document if (token[1] in pos_set)]
    # elapsed_time = time.perf_counter() - start_time
    # print("POS", elapsed_time)

    ####################################################################################################################
    # Removing digits, punctuation and whitespace
    ####################################################################################################################
    # start_time = time.perf_counter()
    tokenized_document_no_punctuation = list()
    append_token = tokenized_document_no_punctuation.append
    for token in tokenized_document:
        new_token = remove_digits_punctuation_whitespace(token, digits_punctuation_whitespace_re)
        if not new_token == u'':
            append_token(new_token)
    # elapsed_time = time.perf_counter() - start_time
    # print("digits etc", elapsed_time)

    ####################################################################################################################
    # Removing stopwords
    ####################################################################################################################
    # start_time = time.perf_counter()
    tokenized_document_no_stopwords = list()
    append_word = tokenized_document_no_stopwords.append
    for word in tokenized_document_no_punctuation:
        if word not in stopset:
            append_word(word)
    # elapsed_time = time.perf_counter() - start_time
    # print("stopwords 1", elapsed_time)

    ####################################################################################################################
    # Stemming and Lemmatizing
    ####################################################################################################################
    # start_time = time.perf_counter()
    lemma_to_keywordbag = defaultdict(lambda: defaultdict(int))

    final_doc = list()
    append_lemma = final_doc.append
    for word in tokenized_document_no_stopwords:
        lemma = lemmatize(word)
        append_lemma(lemma)
        lemma_to_keywordbag[lemma][word] += 1
    # elapsed_time = time.perf_counter() - start_time
    # print("lemmatize", elapsed_time)

    ####################################################################################################################
    # One more stopword removal
    ####################################################################################################################
    # start_time = time.perf_counter()
    lemma_list = list()
    append_word = lemma_list.append
    for word in final_doc:
        if word not in stopset:
            append_word(word)
    # elapsed_time = time.perf_counter() - start_time
    # print("stopwords 2", elapsed_time)

    return lemma_list, lemma_to_keywordbag
Extracts a clean bag-of-words from a document.

    Inputs: - document: A string containing some text.

    Output: - lemma_list: A python list of lemmas or stems.
            - lemma_to_keywordbag: A python dictionary that maps stems/lemmas to original topic keywords.