Files
doczyai-pipelines/fieldExtraction/src/utils.py
T

226 lines
6.9 KiB
Python
Raw Normal View History

import os
import re
import pandas as pd
import shutil
import time
import sys
import numpy as np
import config
def read_local(file_path):
# Check if the file is a text file
if os.path.isfile(file_path) and file_path.endswith(".txt"):
try:
# First attempt to open the file with UTF-8 encoding
with open(file_path, "r", encoding="utf-8") as file:
file_contents = file.read()
return file_contents
except UnicodeDecodeError:
# If UTF-8 fails, try reading the file with ANSI encoding
try:
with open(file_path, "r", encoding="cp1252") as file:
file_contents = file.read()
return file_contents
except UnicodeDecodeError:
# If ANSI also fails, log an error message or handle it accordingly
print(f"Failed to decode {file_path} with UTF-8 and cp1252 encodings.")
def list_s3_files(prefix=config.S3_PREFIX, bucket=config.S3_BUCKET):
"""List all files in an S3 folder."""
response = config.S3_CLIENT.list_objects_v2(Bucket=bucket, Prefix=prefix)
return [item["Key"] for item in response.get("Contents", [])]
def read_s3():
s3_client = config.S3_CLIENT
bucket = config.S3_BUCKET
prefix = config.S3_PREFIX
file_list = []
continuation_token = None
while True:
if continuation_token:
response = s3_client.list_objects_v2(
Bucket=bucket, Prefix=prefix, ContinuationToken=continuation_token
)
else:
response = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix)
file_list += [
obj["Key"]
for obj in response.get("Contents", [])
if not obj["Key"].endswith("/")
]
if response.get("IsTruncated"):
continuation_token = response.get("NextContinuationToken")
else:
break
contract_list = sorted(file_list)
files = {}
for contract in contract_list:
print(f"Reading {contract}")
try:
data = s3_client.get_object(Bucket=bucket, Key=contract)
contents = data["Body"].read()
context = contents.decode("utf-8")
path, filename = os.path.split(contract)
files[filename] = context
except:
pass
return files
def read_input(local_path=config.LOCAL_PATH):
if config.READ_MODE == "local":
files = {}
for file in os.listdir(local_path):
full_path = os.path.join(local_path, file)
file_text = read_local(full_path)
files[file] = file_text
return files
elif config.READ_MODE == "s3":
return read_s3()
def consolidate_individual(input_folder="results", output_folder="output"):
dfs = []
for filename in os.listdir(input_folder):
if filename.endswith(".csv"):
filepath = os.path.join(input_folder, filename)
dfs.append(pd.read_csv(filepath))
# Remove temp folder
if input_folder == "temp" and os.path.exists(input_folder):
shutil.rmtree(input_folder)
consolidated_df = pd.concat(dfs, ignore_index=True)
# Write output
version = 1
existing_files = [
filename
for filename in os.listdir(output_folder)
if filename.startswith(f"consolidated_results_{config.TODAY}")
]
if existing_files:
versions = [
int(file.split("_v")[1].split(".")[0])
for file in existing_files
if "_v" in file
]
if versions:
version = max(versions) + 1
filename = f"consolidated_results_{config.TODAY}_v{version}.csv"
consolidated_df.to_csv(os.path.join(output_folder, filename))
def preprocess_text_file(file_path):
# Attempt to open the file with UTF-8 encoding first
try:
with open(file_path, "r", encoding="utf-8") as file:
text = file.read()
except UnicodeDecodeError:
# If UTF-8 fails, try reading the file with ANSI (cp1252) encoding
try:
with open(file_path, "r", encoding="cp1252") as file:
text = file.read()
except UnicodeDecodeError:
# If ANSI also fails, log an error message or handle it accordingly
print(f"Failed to decode {file_path} with UTF-8 and cp1252 encodings.")
return []
# Split the text into pages based on a specific marker
pages = re.split(r"Start of Page No\. = \d+", text)
return pages
def format_td_check(td_dicts, dont_include_list):
final_str = ""
dict_count = 1
for td_dict in td_dicts:
final_str += str(dict_count) + ". "
for k in td_dict.keys():
if k not in dont_include_list:
final_str += k + ": " + td_dict[k] + ", "
final_str += "\n"
dict_count += 1
return final_str
def contains_reimbursement(text, page="1"):
if isinstance(text, dict):
return page.isdigit() and (
"%" in text[page]
or "$" in text[page]
or "percent " in text[page]
or "compensation schedule" in text[page].lower()
or "reimbursement schedule" in text[page].lower()
)
elif isinstance(text, str):
return (
"%" in text
or "$" in text
or "percent " in text
or "compensation schedule" in text.lower()
or "reimbursement schedule" in text.lower()
)
else:
print("contains_reimbursement - Invalid data type")
def contains_keyword(text, keywords):
# FILL OUT HERE
return
def filter_already_processed(input_dict, fields=config.FIELDS):
already_processed = []
for folder_name in os.listdir(config.OUTPUT_DIRECTORY):
# ABC
if (
fields == "abc"
and config.AC_RESULTS_NAME
in os.listdir(os.path.join(config.OUTPUT_DIRECTORY, folder_name))
and config.B_RESULTS_NAME
in os.listdir(os.path.join(config.OUTPUT_DIRECTORY, folder_name))
):
already_processed.append(folder_name + ".txt")
# Fill AC Here
if (
config.AC_RESULTS_NAME
in os.listdir(os.path.join(config.OUTPUT_DIRECTORY, folder_name))
and config.FIELDS == "ac"
):
already_processed.append(folder_name + ".txt")
# Fill B Here
if (
config.B_RESULTS_NAME
in os.listdir(os.path.join(config.OUTPUT_DIRECTORY, folder_name))
and config.FIELDS == "b"
):
already_processed.append(folder_name + ".txt")
input_dict = {
key: input_dict[key]
for key in input_dict.keys()
if key not in already_processed
}
return input_dict
def is_empty(value):
if pd.isna(value):
return True
else:
empty_values = [None, "", "N/A", "NA", "null", "none", "NaN", np.nan, "nan"]
return value in empty_values