Forms a user-term matrix.

    Input:   - user_twitter_list_keywords_gen: A python generator that yields a user Twitter id and a bag-of-words.
             - id_to_node:  A Twitter id to node map as a python dictionary.
             - lemma_set: For the labelling, we use only lemmas in this set. Default: None

    Outputs: - user_term_matrix: A user-to-term matrix in scipy sparse matrix format.
             - annotated_nodes: A numpy array containing graph nodes.
             - label_to_topic: A python dictionary that maps a numerical label to a string topic/keyword.
             - node_to_lemma_tokeywordbag: A python dictionary that maps nodes to lemma-to-keyword bags.

def form_user_term_matrix(user_twitter_list_keywords_gen, id_to_node, lemma_set=None, keyword_to_topic_manual=None):
    """
    Forms a user-term matrix.

    Input:   - user_twitter_list_keywords_gen: A python generator that yields a user Twitter id and a bag-of-words.
             - id_to_node:  A Twitter id to node map as a python dictionary.
             - lemma_set: For the labelling, we use only lemmas in this set. Default: None

    Outputs: - user_term_matrix: A user-to-term matrix in scipy sparse matrix format.
             - annotated_nodes: A numpy array containing graph nodes.
             - label_to_topic: A python dictionary that maps a numerical label to a string topic/keyword.
             - node_to_lemma_tokeywordbag: A python dictionary that maps nodes to lemma-to-keyword bags.
    """
    # Prepare for iteration.
    term_to_attribute = dict()

    user_term_matrix_row = list()
    user_term_matrix_col = list()
    user_term_matrix_data = list()

    append_user_term_matrix_row = user_term_matrix_row.append
    append_user_term_matrix_col = user_term_matrix_col.append
    append_user_term_matrix_data = user_term_matrix_data.append

    annotated_nodes = list()
    append_node = annotated_nodes.append

    node_to_lemma_tokeywordbag = dict()

    invalid_terms = list()
    counter = 0

    if keyword_to_topic_manual is not None:
        manual_keyword_list = list(keyword_to_topic_manual.keys())

    for user_twitter_id, user_annotation in user_twitter_list_keywords_gen:
        counter += 1
        # print(counter)
        bag_of_words = user_annotation["bag_of_lemmas"]
        lemma_to_keywordbag = user_annotation["lemma_to_keywordbag"]

        if lemma_set is not None:
            bag_of_words = {lemma: multiplicity for lemma, multiplicity in bag_of_words.items() if lemma in lemma_set}
            lemma_to_keywordbag = {lemma: keywordbag for lemma, keywordbag in lemma_to_keywordbag.items() if lemma in lemma_set}

        node = id_to_node[user_twitter_id]
        append_node(node)
        node_to_lemma_tokeywordbag[node] = lemma_to_keywordbag
        for term, multiplicity in bag_of_words.items():
            if term == "news":
                continue

            if keyword_to_topic_manual is not None:
                keyword_bag = lemma_to_keywordbag[term]
                term = max(keyword_bag.keys(), key=(lambda key: keyword_bag[key]))

                found_list_of_words = simple_word_query(term, manual_keyword_list, edit_distance=1)

                if len(found_list_of_words) > 0:
                    term = found_list_of_words[0]

                try:
                    term = keyword_to_topic_manual[term]
                except KeyError:
                    print(term)

            vocabulary_size = len(term_to_attribute)
            attribute = term_to_attribute.setdefault(term, vocabulary_size)

            append_user_term_matrix_row(node)
            append_user_term_matrix_col(attribute)
            append_user_term_matrix_data(multiplicity)

    annotated_nodes = np.array(list(set(annotated_nodes)), dtype=np.int64)

    user_term_matrix_row = np.array(user_term_matrix_row, dtype=np.int64)
    user_term_matrix_col = np.array(user_term_matrix_col, dtype=np.int64)
    user_term_matrix_data = np.array(user_term_matrix_data, dtype=np.float64)

    user_term_matrix = sparse.coo_matrix((user_term_matrix_data,
                                          (user_term_matrix_row, user_term_matrix_col)),
                                         shape=(len(id_to_node), len(term_to_attribute)))

    label_to_topic = dict(zip(term_to_attribute.values(), term_to_attribute.keys()))

    # print(user_term_matrix.shape)
    # print(len(label_to_topic))
    # print(invalid_terms)

    return user_term_matrix, annotated_nodes, label_to_topic, node_to_lemma_tokeywordbag