Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -599,8 +599,11 @@ def generate_pdf_content(summary, preview, anomalies, amc_reminders, insights, d
|
|
| 599 |
def validate_and_generate_pdf(summary, preview, anomalies, amc_reminders, insights, device_cards, daily_log_chart, weekly_uptime_chart, anomaly_alerts_chart, downtime_chart, df, month_filter):
|
| 600 |
if not all([summary, preview, anomalies, amc_reminders, insights, device_cards, df is not None]):
|
| 601 |
logging.error("One or more required inputs for PDF generation are missing.")
|
| 602 |
-
return None
|
| 603 |
-
|
|
|
|
|
|
|
|
|
|
| 604 |
|
| 605 |
# Main Gradio function
|
| 606 |
async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_range, month_filter, last_modified_state):
|
|
@@ -608,18 +611,18 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 608 |
start_time = datetime.now()
|
| 609 |
|
| 610 |
if not file_obj:
|
| 611 |
-
return "No file uploaded.", "No data to preview.", None, '<p>No device cards available.</p>', None, None, None, None, "No anomalies detected.", "No AMC reminders.", "No insights generated.", None, last_modified_state, None, None, None, None, None, None
|
| 612 |
|
| 613 |
file_path = file_obj.name
|
| 614 |
current_modified_time = os.path.getmtime(file_path)
|
| 615 |
|
| 616 |
if last_modified_state and current_modified_time == last_modified_state:
|
| 617 |
-
return None, None, None, None, None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None
|
| 618 |
|
| 619 |
logging.info(f"Processing file: {file_path}, last modified: {current_modified_time}")
|
| 620 |
|
| 621 |
if not file_path.endswith(".csv"):
|
| 622 |
-
return "Please upload a CSV file.", "", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, last_modified_state, None, None, None, None, None, None
|
| 623 |
|
| 624 |
required_columns = ["device_id", "log_type", "status", "timestamp", "usage_hours", "downtime", "amc_date"]
|
| 625 |
dtypes = {
|
|
@@ -633,7 +636,7 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 633 |
df = pd.read_csv(file_path, dtype=dtypes)
|
| 634 |
missing_columns = [col for col in required_columns if col not in df.columns]
|
| 635 |
if missing_columns:
|
| 636 |
-
return f"Missing columns: {missing_columns}", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None
|
| 637 |
|
| 638 |
df["timestamp"] = pd.to_datetime(df["timestamp"], errors='coerce')
|
| 639 |
df["amc_date"] = pd.to_datetime(df["amc_date"], errors='coerce')
|
|
@@ -641,7 +644,7 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 641 |
logging.info("Localizing naive timestamps to IST")
|
| 642 |
df["timestamp"] = df["timestamp"].dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
|
| 643 |
if df.empty:
|
| 644 |
-
return "No data available.", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None
|
| 645 |
|
| 646 |
logging.info(f"DataFrame before filtering:\n{df.head().to_string()}")
|
| 647 |
|
|
@@ -676,7 +679,7 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 676 |
|
| 677 |
if filtered_df.empty:
|
| 678 |
logging.warning("Filtered DataFrame is empty after applying filters.")
|
| 679 |
-
return "No data after applying filters.", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None
|
| 680 |
|
| 681 |
logging.info(f"Filtered DataFrame:\n{filtered_df.head().to_string()}")
|
| 682 |
|
|
@@ -796,10 +799,13 @@ async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_ra
|
|
| 796 |
if elapsed_time > 10:
|
| 797 |
logging.warning(f"Processing time exceeded 10 seconds: {elapsed_time:.2f} seconds")
|
| 798 |
|
| 799 |
-
|
|
|
|
|
|
|
|
|
|
| 800 |
except Exception as e:
|
| 801 |
logging.error(f"Failed to process file: {str(e)}")
|
| 802 |
-
return f"Error: {str(e)}", None, None, '<p>Error processing data.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None
|
| 803 |
|
| 804 |
# Update filter options
|
| 805 |
def update_filters(file_obj):
|
|
@@ -867,6 +873,7 @@ try:
|
|
| 867 |
insights_state = gr.State()
|
| 868 |
device_cards_state = gr.State()
|
| 869 |
df_state = gr.State()
|
|
|
|
| 870 |
|
| 871 |
with gr.Row():
|
| 872 |
with gr.Column(scale=1):
|
|
@@ -907,6 +914,10 @@ try:
|
|
| 907 |
with gr.Group(elem_classes="dashboard-container"):
|
| 908 |
gr.Markdown("<div class='dashboard-title'>Analysis Results</div>")
|
| 909 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
with gr.Group(elem_classes="dashboard-section"):
|
| 911 |
gr.Markdown("### Step 1: Summary Report")
|
| 912 |
summary_output = gr.Markdown()
|
|
@@ -946,7 +957,7 @@ try:
|
|
| 946 |
|
| 947 |
with gr.Group(elem_classes="dashboard-section"):
|
| 948 |
gr.Markdown("### Export Report")
|
| 949 |
-
pdf_button = gr.Button("Generate PDF Report")
|
| 950 |
pdf_output = gr.File(label="Download Monthly Status Report as PDF")
|
| 951 |
|
| 952 |
file_input.change(
|
|
@@ -986,10 +997,22 @@ try:
|
|
| 986 |
amc_reminders_state,
|
| 987 |
insights_state,
|
| 988 |
device_cards_state,
|
| 989 |
-
df_state
|
|
|
|
|
|
|
| 990 |
]
|
| 991 |
)
|
| 992 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 993 |
pdf_button.click(
|
| 994 |
fn=validate_and_generate_pdf,
|
| 995 |
inputs=[
|
|
@@ -1006,7 +1029,7 @@ try:
|
|
| 1006 |
df_state,
|
| 1007 |
month_filter
|
| 1008 |
],
|
| 1009 |
-
outputs=[pdf_output]
|
| 1010 |
)
|
| 1011 |
|
| 1012 |
logging.info("Gradio interface initialized successfully")
|
|
|
|
| 599 |
def validate_and_generate_pdf(summary, preview, anomalies, amc_reminders, insights, device_cards, daily_log_chart, weekly_uptime_chart, anomaly_alerts_chart, downtime_chart, df, month_filter):
|
| 600 |
if not all([summary, preview, anomalies, amc_reminders, insights, device_cards, df is not None]):
|
| 601 |
logging.error("One or more required inputs for PDF generation are missing.")
|
| 602 |
+
return None, "Please click 'Analyze' to process the data before generating a PDF."
|
| 603 |
+
pdf_path = generate_pdf_content(summary, preview, anomalies, amc_reminders, insights, device_cards, daily_log_chart, weekly_uptime_chart, anomaly_alerts_chart, downtime_chart, df, month_filter)
|
| 604 |
+
if pdf_path is None:
|
| 605 |
+
return None, "Failed to generate PDF. Check logs for details."
|
| 606 |
+
return pdf_path, "PDF generated successfully."
|
| 607 |
|
| 608 |
# Main Gradio function
|
| 609 |
async def process_logs(file_obj, lab_site_filter, equipment_type_filter, date_range, month_filter, last_modified_state):
|
|
|
|
| 611 |
start_time = datetime.now()
|
| 612 |
|
| 613 |
if not file_obj:
|
| 614 |
+
return "No file uploaded.", "No data to preview.", None, '<p>No device cards available.</p>', None, None, None, None, "No anomalies detected.", "No AMC reminders.", "No insights generated.", None, last_modified_state, None, None, None, None, None, None, False, "Please upload a CSV file to analyze."
|
| 615 |
|
| 616 |
file_path = file_obj.name
|
| 617 |
current_modified_time = os.path.getmtime(file_path)
|
| 618 |
|
| 619 |
if last_modified_state and current_modified_time == last_modified_state:
|
| 620 |
+
return None, None, None, None, None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None, False, "No changes detected in the file."
|
| 621 |
|
| 622 |
logging.info(f"Processing file: {file_path}, last modified: {current_modified_time}")
|
| 623 |
|
| 624 |
if not file_path.endswith(".csv"):
|
| 625 |
+
return "Please upload a CSV file.", "", None, '<p>No device cards available.</p>', None, None, None, None, "", "", "", None, last_modified_state, None, None, None, None, None, None, False, "Invalid file format. Please upload a CSV file."
|
| 626 |
|
| 627 |
required_columns = ["device_id", "log_type", "status", "timestamp", "usage_hours", "downtime", "amc_date"]
|
| 628 |
dtypes = {
|
|
|
|
| 636 |
df = pd.read_csv(file_path, dtype=dtypes)
|
| 637 |
missing_columns = [col for col in required_columns if col not in df.columns]
|
| 638 |
if missing_columns:
|
| 639 |
+
return f"Missing columns: {missing_columns}", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None, False, f"Missing required columns: {missing_columns}"
|
| 640 |
|
| 641 |
df["timestamp"] = pd.to_datetime(df["timestamp"], errors='coerce')
|
| 642 |
df["amc_date"] = pd.to_datetime(df["amc_date"], errors='coerce')
|
|
|
|
| 644 |
logging.info("Localizing naive timestamps to IST")
|
| 645 |
df["timestamp"] = df["timestamp"].dt.tz_localize('UTC').dt.tz_convert('Asia/Kolkata')
|
| 646 |
if df.empty:
|
| 647 |
+
return "No data available.", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None, False, "No data available in the uploaded file."
|
| 648 |
|
| 649 |
logging.info(f"DataFrame before filtering:\n{df.head().to_string()}")
|
| 650 |
|
|
|
|
| 679 |
|
| 680 |
if filtered_df.empty:
|
| 681 |
logging.warning("Filtered DataFrame is empty after applying filters.")
|
| 682 |
+
return "No data after applying filters.", None, None, '<p>No device cards available.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None, False, "No data available after applying filters."
|
| 683 |
|
| 684 |
logging.info(f"Filtered DataFrame:\n{filtered_df.head().to_string()}")
|
| 685 |
|
|
|
|
| 799 |
if elapsed_time > 10:
|
| 800 |
logging.warning(f"Processing time exceeded 10 seconds: {elapsed_time:.2f} seconds")
|
| 801 |
|
| 802 |
+
# Log state variable assignments for debugging
|
| 803 |
+
logging.info(f"Setting state variables: summary={summary}, preview={preview_text}, anomalies={anomalies}, amc_reminders={amc_reminders}, insights={insights}, device_cards={device_cards[:50]}..., df={'set' if df is not None else 'None'}")
|
| 804 |
+
|
| 805 |
+
return (summary, preview_html, usage_chart, device_cards, daily_log_chart, weekly_uptime_chart, anomaly_alerts_chart, downtime_chart, anomalies, amc_reminders, insights, pdf_file, current_modified_time, summary, preview_text, anomalies, amc_reminders, insights, device_cards, filtered_df, True, "Analysis completed successfully. You can now generate the PDF report.")
|
| 806 |
except Exception as e:
|
| 807 |
logging.error(f"Failed to process file: {str(e)}")
|
| 808 |
+
return f"Error: {str(e)}", None, None, '<p>Error processing data.</p>', None, None, None, None, None, None, None, None, last_modified_state, None, None, None, None, None, None, False, f"Failed to process file: {str(e)}"
|
| 809 |
|
| 810 |
# Update filter options
|
| 811 |
def update_filters(file_obj):
|
|
|
|
| 873 |
insights_state = gr.State()
|
| 874 |
device_cards_state = gr.State()
|
| 875 |
df_state = gr.State()
|
| 876 |
+
is_analyzed_state = gr.State(value=False)
|
| 877 |
|
| 878 |
with gr.Row():
|
| 879 |
with gr.Column(scale=1):
|
|
|
|
| 914 |
with gr.Group(elem_classes="dashboard-container"):
|
| 915 |
gr.Markdown("<div class='dashboard-title'>Analysis Results</div>")
|
| 916 |
|
| 917 |
+
with gr.Group(elem_classes="dashboard-section"):
|
| 918 |
+
gr.Markdown("### Status Message")
|
| 919 |
+
status_message = gr.Markdown("Please upload a CSV file and click 'Analyze' to begin.")
|
| 920 |
+
|
| 921 |
with gr.Group(elem_classes="dashboard-section"):
|
| 922 |
gr.Markdown("### Step 1: Summary Report")
|
| 923 |
summary_output = gr.Markdown()
|
|
|
|
| 957 |
|
| 958 |
with gr.Group(elem_classes="dashboard-section"):
|
| 959 |
gr.Markdown("### Export Report")
|
| 960 |
+
pdf_button = gr.Button("Generate PDF Report", interactive=False) # Disabled by default
|
| 961 |
pdf_output = gr.File(label="Download Monthly Status Report as PDF")
|
| 962 |
|
| 963 |
file_input.change(
|
|
|
|
| 997 |
amc_reminders_state,
|
| 998 |
insights_state,
|
| 999 |
device_cards_state,
|
| 1000 |
+
df_state,
|
| 1001 |
+
is_analyzed_state,
|
| 1002 |
+
status_message
|
| 1003 |
]
|
| 1004 |
)
|
| 1005 |
|
| 1006 |
+
def update_pdf_button_interactivity(is_analyzed):
|
| 1007 |
+
return gr.update(interactive=is_analyzed)
|
| 1008 |
+
|
| 1009 |
+
is_analyzed_state.change(
|
| 1010 |
+
fn=update_pdf_button_interactivity,
|
| 1011 |
+
inputs=[is_analyzed_state],
|
| 1012 |
+
outputs=[pdf_button],
|
| 1013 |
+
queue=False
|
| 1014 |
+
)
|
| 1015 |
+
|
| 1016 |
pdf_button.click(
|
| 1017 |
fn=validate_and_generate_pdf,
|
| 1018 |
inputs=[
|
|
|
|
| 1029 |
df_state,
|
| 1030 |
month_filter
|
| 1031 |
],
|
| 1032 |
+
outputs=[pdf_output, status_message]
|
| 1033 |
)
|
| 1034 |
|
| 1035 |
logging.info("Gradio interface initialized successfully")
|