Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2,28 +2,28 @@
|
|
2 |
|
3 |
# -*- coding: utf-8 -*-
|
4 |
#
|
5 |
-
# PROJECT: CognitiveEDA v5.
|
6 |
#
|
7 |
-
# DESCRIPTION: Main application entry point. This definitive version
|
8 |
-
#
|
|
|
|
|
9 |
#
|
10 |
# SETUP: $ pip install -r requirements.txt
|
11 |
#
|
12 |
# AUTHOR: An MCP & PhD Expert in Data & AI Solutions
|
13 |
-
# VERSION: 5.
|
14 |
-
# LAST-UPDATE: 2023-10-30 (
|
15 |
|
16 |
import warnings
|
17 |
import logging
|
18 |
import gradio as gr
|
19 |
|
20 |
-
#
|
21 |
-
from ui.layout import create_main_layout
|
22 |
from ui import callbacks
|
23 |
from core.config import settings
|
24 |
|
25 |
# --- Configuration & Setup ---
|
26 |
-
# This setup MUST be in the global scope to be configured before any functions run.
|
27 |
logging.basicConfig(
|
28 |
level=logging.INFO,
|
29 |
format='%(asctime)s - [%(levelname)s] - (%(filename)s:%(lineno)d) - %(message)s'
|
@@ -36,32 +36,100 @@ def main():
|
|
36 |
Primary function to build, wire up, and launch the Gradio application.
|
37 |
"""
|
38 |
logging.info(f"Starting {settings.APP_TITLE}")
|
39 |
-
|
40 |
-
# The 'with' block creates the Gradio context. All UI and
|
41 |
-
# MUST be defined within this block.
|
42 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"), title=settings.APP_TITLE) as demo:
|
43 |
|
44 |
-
#
|
45 |
-
#
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
-
#
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
# --- Primary Analysis Chain ---
|
52 |
-
# Event 1: User clicks "Generate". This triggers the fast, initial analysis.
|
53 |
analysis_complete_event = components["analyze_button"].click(
|
54 |
fn=callbacks.run_initial_analysis,
|
55 |
inputs=[components["upload_button"]],
|
56 |
outputs=[components["state_analyzer"]]
|
57 |
)
|
58 |
-
|
59 |
-
# Event 2: Chained to the success of Event 1. This triggers the slower,
|
60 |
-
# asynchronous report and visual generation.
|
61 |
analysis_complete_event.then(
|
62 |
fn=callbacks.generate_reports_and_visuals,
|
63 |
inputs=[components["state_analyzer"]],
|
64 |
-
outputs=components
|
65 |
)
|
66 |
|
67 |
# --- Interactive Explorer Callbacks ---
|
@@ -70,43 +138,26 @@ def main():
|
|
70 |
inputs=[components["state_analyzer"], components["dd_hist_col"]],
|
71 |
outputs=[components["plot_histogram"]]
|
72 |
)
|
73 |
-
|
74 |
-
# For the scatter plot, we need to listen to changes on all three dropdowns.
|
75 |
scatter_inputs = [
|
76 |
-
components["state_analyzer"],
|
77 |
-
components["
|
78 |
-
components["dd_scatter_y"],
|
79 |
-
components["dd_scatter_color"]
|
80 |
]
|
81 |
for dropdown in [components["dd_scatter_x"], components["dd_scatter_y"], components["dd_scatter_color"]]:
|
82 |
dropdown.change(
|
83 |
-
fn=callbacks.create_scatterplot,
|
84 |
-
inputs=scatter_inputs,
|
85 |
-
outputs=[components["plot_scatter"]]
|
86 |
)
|
87 |
|
88 |
# --- Specialized Module Callbacks ---
|
89 |
components["num_clusters"].change(
|
90 |
fn=callbacks.update_clustering,
|
91 |
inputs=[components["state_analyzer"], components["num_clusters"]],
|
92 |
-
outputs=[
|
93 |
-
components["plot_cluster"],
|
94 |
-
components["plot_elbow"],
|
95 |
-
components["md_cluster_summary"]
|
96 |
-
]
|
97 |
)
|
98 |
|
99 |
-
# 3. Launch the application server
|
100 |
-
# but is called on the 'demo' object that was defined by it. The server
|
101 |
-
# will now run indefinitely, listening for requests.
|
102 |
demo.launch(debug=False, server_name="0.0.0.0")
|
103 |
|
104 |
|
105 |
# --- Application Entry Point ---
|
106 |
-
# This is the most critical part for a runnable script. The `if __name__ == "__main__":`
|
107 |
-
# check ensures that the `main()` function is called only when the script is
|
108 |
-
# executed directly (not when it's imported by another script). Without this
|
109 |
-
# block, the application will define the 'main' function but never run it,
|
110 |
-
# leading to the "application not initialized" error.
|
111 |
if __name__ == "__main__":
|
112 |
main()
|
|
|
2 |
|
3 |
# -*- coding: utf-8 -*-
|
4 |
#
|
5 |
+
# PROJECT: CognitiveEDA v5.4 - The QuantumLeap Intelligence Platform
|
6 |
#
|
7 |
+
# DESCRIPTION: Main application entry point. This definitive version combines UI
|
8 |
+
# layout and callback registration within a single, robust script
|
9 |
+
# to align with Gradio's context-based API design, resolving all
|
10 |
+
# previous startup errors.
|
11 |
#
|
12 |
# SETUP: $ pip install -r requirements.txt
|
13 |
#
|
14 |
# AUTHOR: An MCP & PhD Expert in Data & AI Solutions
|
15 |
+
# VERSION: 5.4 (Definitive Context-Aware Edition)
|
16 |
+
# LAST-UPDATE: 2023-10-30 (Final architectural correction)
|
17 |
|
18 |
import warnings
|
19 |
import logging
|
20 |
import gradio as gr
|
21 |
|
22 |
+
# The callback LOGIC is still neatly separated
|
|
|
23 |
from ui import callbacks
|
24 |
from core.config import settings
|
25 |
|
26 |
# --- Configuration & Setup ---
|
|
|
27 |
logging.basicConfig(
|
28 |
level=logging.INFO,
|
29 |
format='%(asctime)s - [%(levelname)s] - (%(filename)s:%(lineno)d) - %(message)s'
|
|
|
36 |
Primary function to build, wire up, and launch the Gradio application.
|
37 |
"""
|
38 |
logging.info(f"Starting {settings.APP_TITLE}")
|
39 |
+
|
40 |
+
# The 'with' block creates the Gradio context. All UI and events will be defined here.
|
|
|
41 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"), title=settings.APP_TITLE) as demo:
|
42 |
|
43 |
+
# ======================================================================
|
44 |
+
# 1. DEFINE THE UI LAYOUT DIRECTLY WITHIN THE MAIN SCRIPT
|
45 |
+
# This is the most robust pattern and resolves all context-related errors.
|
46 |
+
# ======================================================================
|
47 |
+
|
48 |
+
# State object to hold the DataAnalyzer instance
|
49 |
+
state_analyzer = gr.State()
|
50 |
+
|
51 |
+
# --- Header ---
|
52 |
+
gr.Markdown(f"<h1>{settings.APP_TITLE}</h1>")
|
53 |
+
gr.Markdown("A world-class data discovery platform that provides a complete suite of EDA tools and intelligently unlocks specialized analysis modules.")
|
54 |
+
|
55 |
+
# --- Input Row ---
|
56 |
+
with gr.Row():
|
57 |
+
upload_button = gr.File(label="1. Upload Data File (CSV, Excel)", file_types=[".csv", ".xlsx"], scale=3)
|
58 |
+
analyze_button = gr.Button("β¨ Generate Intelligence Report", variant="primary", scale=1)
|
59 |
|
60 |
+
# --- Main Tabs ---
|
61 |
+
with gr.Tabs():
|
62 |
+
with gr.Tab("π€ AI-Powered Strategy Report", id="tab_ai"):
|
63 |
+
ai_report_output = gr.Markdown("### Your AI-generated report will appear here after analysis...")
|
64 |
+
|
65 |
+
with gr.Tab("π Data Profile", id="tab_profile"):
|
66 |
+
with gr.Accordion("Missing Values Report", open=False):
|
67 |
+
profile_missing_df = gr.DataFrame()
|
68 |
+
with gr.Accordion("Numeric Features Summary", open=True):
|
69 |
+
profile_numeric_df = gr.DataFrame()
|
70 |
+
with gr.Accordion("Categorical Features Summary", open=True):
|
71 |
+
profile_categorical_df = gr.DataFrame()
|
72 |
+
|
73 |
+
with gr.Tab("π Overview Visuals", id="tab_overview"):
|
74 |
+
with gr.Row():
|
75 |
+
plot_types = gr.Plot()
|
76 |
+
plot_missing = gr.Plot()
|
77 |
+
plot_correlation = gr.Plot()
|
78 |
+
|
79 |
+
with gr.Tab("π¨ Interactive Explorer", id="tab_explorer"):
|
80 |
+
gr.Markdown("### Univariate Analysis")
|
81 |
+
with gr.Row():
|
82 |
+
dd_hist_col = gr.Dropdown(label="Select Column for Histogram", interactive=True)
|
83 |
+
plot_histogram = gr.Plot()
|
84 |
+
gr.Markdown("### Bivariate Analysis")
|
85 |
+
with gr.Row():
|
86 |
+
with gr.Column(scale=1):
|
87 |
+
dd_scatter_x = gr.Dropdown(label="X-Axis (Numeric)", interactive=True)
|
88 |
+
dd_scatter_y = gr.Dropdown(label="Y-Axis (Numeric)", interactive=True)
|
89 |
+
dd_scatter_color = gr.Dropdown(label="Color By (Optional)", interactive=True)
|
90 |
+
with gr.Column(scale=2):
|
91 |
+
plot_scatter = gr.Plot()
|
92 |
+
|
93 |
+
with gr.Tab("π§© Clustering (K-Means)", id="tab_cluster", visible=False) as tab_cluster:
|
94 |
+
with gr.Row():
|
95 |
+
with gr.Column(scale=1):
|
96 |
+
num_clusters = gr.Slider(minimum=2, maximum=10, value=3, step=1, label="Number of Clusters (K)", interactive=True)
|
97 |
+
md_cluster_summary = gr.Markdown()
|
98 |
+
with gr.Column(scale=2):
|
99 |
+
plot_cluster = gr.Plot()
|
100 |
+
plot_elbow = gr.Plot()
|
101 |
+
|
102 |
+
tab_timeseries = gr.Tab("β Time-Series Analysis", id="tab_timeseries", visible=False)
|
103 |
+
tab_text = gr.Tab("π Text Analysis", id="tab_text", visible=False)
|
104 |
+
|
105 |
+
# --- Collect all components into a dictionary for easy access ---
|
106 |
+
components = {
|
107 |
+
"state_analyzer": state_analyzer, "upload_button": upload_button, "analyze_button": analyze_button,
|
108 |
+
"ai_report_output": ai_report_output, "profile_missing_df": profile_missing_df,
|
109 |
+
"profile_numeric_df": profile_numeric_df, "profile_categorical_df": profile_categorical_df,
|
110 |
+
"plot_types": plot_types, "plot_missing": plot_missing, "plot_correlation": plot_correlation,
|
111 |
+
"dd_hist_col": dd_hist_col, "plot_histogram": plot_histogram, "dd_scatter_x": dd_scatter_x,
|
112 |
+
"dd_scatter_y": dd_scatter_y, "dd_scatter_color": dd_scatter_color, "plot_scatter": plot_scatter,
|
113 |
+
"tab_timeseries": tab_timeseries, "tab_text": tab_text, "tab_cluster": tab_cluster,
|
114 |
+
"num_clusters": num_clusters, "md_cluster_summary": md_cluster_summary,
|
115 |
+
"plot_cluster": plot_cluster, "plot_elbow": plot_elbow,
|
116 |
+
}
|
117 |
+
|
118 |
+
# ======================================================================
|
119 |
+
# 2. REGISTER EVENT HANDLERS
|
120 |
+
# Now that components is a guaranteed dictionary, this will work.
|
121 |
+
# ======================================================================
|
122 |
|
123 |
# --- Primary Analysis Chain ---
|
|
|
124 |
analysis_complete_event = components["analyze_button"].click(
|
125 |
fn=callbacks.run_initial_analysis,
|
126 |
inputs=[components["upload_button"]],
|
127 |
outputs=[components["state_analyzer"]]
|
128 |
)
|
|
|
|
|
|
|
129 |
analysis_complete_event.then(
|
130 |
fn=callbacks.generate_reports_and_visuals,
|
131 |
inputs=[components["state_analyzer"]],
|
132 |
+
outputs=components
|
133 |
)
|
134 |
|
135 |
# --- Interactive Explorer Callbacks ---
|
|
|
138 |
inputs=[components["state_analyzer"], components["dd_hist_col"]],
|
139 |
outputs=[components["plot_histogram"]]
|
140 |
)
|
|
|
|
|
141 |
scatter_inputs = [
|
142 |
+
components["state_analyzer"], components["dd_scatter_x"],
|
143 |
+
components["dd_scatter_y"], components["dd_scatter_color"]
|
|
|
|
|
144 |
]
|
145 |
for dropdown in [components["dd_scatter_x"], components["dd_scatter_y"], components["dd_scatter_color"]]:
|
146 |
dropdown.change(
|
147 |
+
fn=callbacks.create_scatterplot, inputs=scatter_inputs, outputs=[components["plot_scatter"]]
|
|
|
|
|
148 |
)
|
149 |
|
150 |
# --- Specialized Module Callbacks ---
|
151 |
components["num_clusters"].change(
|
152 |
fn=callbacks.update_clustering,
|
153 |
inputs=[components["state_analyzer"], components["num_clusters"]],
|
154 |
+
outputs=[components["plot_cluster"], components["plot_elbow"], components["md_cluster_summary"]]
|
|
|
|
|
|
|
|
|
155 |
)
|
156 |
|
157 |
+
# 3. Launch the application server
|
|
|
|
|
158 |
demo.launch(debug=False, server_name="0.0.0.0")
|
159 |
|
160 |
|
161 |
# --- Application Entry Point ---
|
|
|
|
|
|
|
|
|
|
|
162 |
if __name__ == "__main__":
|
163 |
main()
|