Finds all frequent (and meaningful) n-grams in a file, treating each new line as a new document.
        
        :param input_reader:    LineReader initialized on file with documents to generate n-grams for
        :param n:               Maximum n-gram length
        :param min_frequency:   Smallest required frequency to include n-gram
        :param min_pmi:         Minimum PMI value for n-gram to be included
        :param filters:         List of filters to apply to document before generating n-grams
        :return:                Map of n-grams as key and number of occurrences as value

def get_frequent_n_grams(self, input_reader, n, min_frequency, min_pmi, filters):
        """
        Finds all frequent (and meaningful) n-grams in a file, treating each new line as a new document.
        
        :param input_reader:    LineReader initialized on file with documents to generate n-grams for
        :param n:               Maximum n-gram length
        :param min_frequency:   Smallest required frequency to include n-gram
        :param min_pmi:         Minimum PMI value for n-gram to be included
        :param filters:         List of filters to apply to document before generating n-grams
        :return:                Map of n-grams as key and number of occurrences as value
        """
        line_counter = 0
        TweetNGramsPMI.tweet_reader = input_reader
        TweetNGramsPMI.n_gram_tree = self.NGramTree()

        # Todo: Parallelize
        for tweet in self.tweet_reader:
            line_counter += 1
            if line_counter % 200000 == 0:
                TweetNGramsPMI.n_gram_tree.prune_infrequent(math.ceil(min_frequency * line_counter / 2.))

            tweet = filters.apply(tweet)
            for sentence in RegexFilters.SENTENCE_END_PUNCTUATION.split(tweet):
                tokens = RegexFilters.WHITESPACE.split(sentence.strip())
                if len(tokens) == 1:
                    continue

                for i in range(len(tokens)):
                    self.n_gram_tree.increment_n_gram(tokens[i:min(i + n, len(tokens))])

        return self.n_gram_tree.get_n_grams(int(min_frequency * line_counter), min_pmi)