CognitiveEDA / app.py
mgbam's picture
Update app.py
0a8cbc3 verified
raw
history blame
4.46 kB
# app.py
# -*- coding: utf-8 -*-
#
# PROJECT: CognitiveEDA v5.3 - The QuantumLeap Intelligence Platform
#
# DESCRIPTION: Main application entry point. This definitive version correctly
# orchestrates UI layout, callback registration, and server launch.
#
# SETUP: $ pip install -r requirements.txt
#
# AUTHOR: An MCP & PhD Expert in Data & AI Solutions
# VERSION: 5.3 (Definitive Launch Edition)
# LAST-UPDATE: 2023-10-30 (Ensured main execution block and all callbacks are wired)
import warnings
import logging
import gradio as gr
# Import the UI layout and the callback LOGIC functions
from ui.layout import create_main_layout
from ui import callbacks
from core.config import settings
# --- Configuration & Setup ---
# This setup MUST be in the global scope to be configured before any functions run.
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - [%(levelname)s] - (%(filename)s:%(lineno)d) - %(message)s'
)
warnings.filterwarnings('ignore', category=FutureWarning)
def main():
"""
Primary function to build, wire up, and launch the Gradio application.
"""
logging.info(f"Starting {settings.APP_TITLE}")
# The 'with' block creates the Gradio context. All UI and event listeners
# MUST be defined within this block.
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"), title=settings.APP_TITLE) as demo:
# 1. Build the UI from the layout module.
# This returns a dictionary of all named components.
components = create_main_layout()
# 2. Register all event handlers (callbacks) within the same context.
# This is the correct, robust pattern for a modular Gradio app.
# --- Primary Analysis Chain ---
# Event 1: User clicks "Generate". This triggers the fast, initial analysis.
analysis_complete_event = components["analyze_button"].click(
fn=callbacks.run_initial_analysis,
inputs=[components["upload_button"]],
outputs=[components["state_analyzer"]]
)
# Event 2: Chained to the success of Event 1. This triggers the slower,
# asynchronous report and visual generation.
analysis_complete_event.then(
fn=callbacks.generate_reports_and_visuals,
inputs=[components["state_analyzer"]],
outputs=components # Maps the returned dict to the components dict
)
# --- Interactive Explorer Callbacks ---
components["dd_hist_col"].change(
fn=callbacks.create_histogram,
inputs=[components["state_analyzer"], components["dd_hist_col"]],
outputs=[components["plot_histogram"]]
)
# For the scatter plot, we need to listen to changes on all three dropdowns.
scatter_inputs = [
components["state_analyzer"],
components["dd_scatter_x"],
components["dd_scatter_y"],
components["dd_scatter_color"]
]
for dropdown in [components["dd_scatter_x"], components["dd_scatter_y"], components["dd_scatter_color"]]:
dropdown.change(
fn=callbacks.create_scatterplot,
inputs=scatter_inputs,
outputs=[components["plot_scatter"]]
)
# --- Specialized Module Callbacks ---
components["num_clusters"].change(
fn=callbacks.update_clustering,
inputs=[components["state_analyzer"], components["num_clusters"]],
outputs=[
components["plot_cluster"],
components["plot_elbow"],
components["md_cluster_summary"]
]
)
# 3. Launch the application server. This line is outside the 'with' block
# but is called on the 'demo' object that was defined by it. The server
# will now run indefinitely, listening for requests.
demo.launch(debug=False, server_name="0.0.0.0")
# --- Application Entry Point ---
# This is the most critical part for a runnable script. The `if __name__ == "__main__":`
# check ensures that the `main()` function is called only when the script is
# executed directly (not when it's imported by another script). Without this
# block, the application will define the 'main' function but never run it,
# leading to the "application not initialized" error.
if __name__ == "__main__":
main()