from itertools import groupby, count import re def clean_newlines(contract_text): """ Cleans up isolated newlines in a contract text, converting them into spaces to ensure text continuity. This function uses a regular expression to identify standalone newlines (those not part of a paragraph break, which typically consists of consecutive newlines) and replaces them with a single space. This process helps in preserving the flow of text and making it more readable and processable, particularly for text extraction and analysis tasks that might be sensitive to abrupt breaks in the text. Parameters: contract_text (str): The text of the contract that may contain sporadic newlines. Returns: str: The cleaned contract text with isolated newlines replaced by spaces. """ cleaned_text = re.sub(r'(?>>' and '<<<' to highlight them. The modified text for each page is then updated in the dictionary, allowing for easier identification and processing of rate-related terms in subsequent analyses. Parameters: text_dict (dict): A dictionary where keys are page numbers and values are the text content of those pages. Returns: dict: The updated dictionary with rate-related terms highlighted in the text of each page. """ for page, text in text_dict.items(): words = text.split() highlighted_words = [] for word in words: if '%' in word or '$' in word: word = f'>>>{word}<<<' highlighted_words.append(word) text_dict[page] = ' '.join(highlighted_words) return text_dict def chunk_text(text_dict): """ Creates text chunks from a dictionary of page texts, focusing on pages with special characters (percentages and dollar amounts). This function identifies pages that contain '%' or '$' signs and includes those pages along with their immediate neighbors (previous and next pages) to form chunks. The chunks are then grouped and concatenated into single text blocks for easier processing. Each chunk is stored in a new dictionary where the keys represent the range of pages included in the chunk. Parameters: text_dict (dict): A dictionary where keys are page numbers (as strings) and values are the text content of those pages. Returns: dict: A new dictionary where each key is a string representing the range of pages in a chunk, and each value is the concatenated text of those pages. """ special_pages = {int(page): text for page, text in text_dict.items() if (('%' in text) or ('$' in text) or ('percent' in text))} page_numbers = sorted(special_pages.keys()) chunk_page_numbers = [] for page in page_numbers: chunk_page_numbers.append(page-1) chunk_page_numbers.append(page) chunk_page_numbers.append(page+1) chunk_page_numbers = list(set(chunk_page_numbers)) chunk_page_numbers = [page for page in chunk_page_numbers if str(page) in text_dict.keys()] chunks = [list(group) for key, group in groupby(chunk_page_numbers, lambda x, c=count(): x - next(c))] chunk_dict = {} for item in chunks: dict_key = f'{min(item)}-{max(item)}' text = "".join([text_dict[str(page)] for page in item]) chunk_dict[dict_key] = text return chunk_dict def clean_billed_charges(contract_text): """ Cleans occurrences of 'billed charges' in a text by replacing them with '100% of billed charges' unless preceded by a percentage. This function uses a regular expression to find all instances of the phrase 'billed charges'. For each match, it checks the preceding text (up to 15 characters before the match) for a percentage sign ('%'). If a percentage is found, it leaves the match unchanged. Otherwise, it replaces 'billed charges' with '100% of billed charges'. Parameters: text (str): The input text to be cleaned. Returns: str: The cleaned text with appropriate replacements made for 'billed charges'. """ substrings = [ "Physician's Billed Charges", "Provider's Billed Charges", "Allowable Billed Charges", "Hospital's Billed Charges", "Physician's Charges", "Provider's Charges", "Allowable Charges", "Hospital's Charges", "Billed Charges", "the rates set forth in this Exhibit", "the rutes set forth in this Exhibit", "Provider's usual and customary charge" ] max_substring_length = max([len(s) for s in substrings]) def find_substring_indices(contract_text, s): indices = [] lower_contract_text = contract_text.lower() lower_s = s.lower() index = lower_contract_text.find(lower_s) while index != -1: indices.append(index) index = lower_contract_text.find(lower_s, index + 1) return indices for s in substrings: indices = find_substring_indices(contract_text, s) index_adder = 0 if indices: for i in indices: index = i+index_adder end_index = index + max_substring_length match_part = contract_text[index:end_index] previous = contract_text[max(0, index-30):index] if '%' not in previous: contract_text = contract_text[0:index] + f" 100% of {match_part}" + contract_text[end_index:] index_adder += 9 return contract_text.replace(' ', ' ')