docs: 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