File size: 4,804 Bytes
0a8cbc3
d9ea3f9
60da408
c9ba3ae
16f99f2
c9ba3ae
16f99f2
 
 
0a8cbc3
 
 
 
16f99f2
 
60da408
0a8cbc3
 
51dfd28
0a8cbc3
 
51dfd28
0d6622c
0a8cbc3
 
 
 
 
60da408
0a8cbc3
 
f311ea6
0a8cbc3
 
16f99f2
f311ea6
 
 
16f99f2
f311ea6
 
16f99f2
 
 
 
 
 
f311ea6
16f99f2
 
 
 
 
 
 
 
 
f311ea6
 
16f99f2
f311ea6
16f99f2
f311ea6
16f99f2
 
 
 
 
 
 
 
 
 
 
 
51dfd28
16f99f2
 
0a8cbc3
16f99f2
 
0a8cbc3
 
 
16f99f2
 
0a8cbc3
0d6622c
16f99f2
 
 
 
 
 
0a8cbc3
 
c9ba3ae
0a8cbc3
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# app.py

# -*- coding: utf-8 -*-
#
# PROJECT:      CognitiveEDA v5.5 - The QuantumLeap Intelligence Platform
#
# DESCRIPTION:  Main application entry point. This definitive version correctly
#               handles multiple outputs by aligning with Gradio's API, passing
#               a list of components to the `outputs` parameter.
#
# SETUP:        $ pip install -r requirements.txt
#
# AUTHOR:       An MCP & PhD Expert in Data & AI Solutions
# VERSION:      5.5 (Final API-Compliant Edition)
# LAST-UPDATE:  2023-10-30 (Corrected multiple output handling)

import warnings
import logging
import gradio as gr

from ui import callbacks
from core.config import settings

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - [%(levelname)s] - (%(filename)s:%(lineno)d) - %(message)s'
)
warnings.filterwarnings('ignore', category=FutureWarning)

def main():
    logging.info(f"Starting {settings.APP_TITLE}")

    with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"), title=settings.APP_TITLE) as demo:
        
        # 1. DEFINE THE UI LAYOUT
        state_analyzer = gr.State()
        gr.Markdown(f"<h1>{settings.APP_TITLE}</h1>")
        with gr.Row():
            upload_button = gr.File(label="1. Upload Data File", file_types=[".csv", ".xlsx"], scale=3)
            analyze_button = gr.Button("✨ Generate Intelligence Report", variant="primary", scale=1)
        with gr.Tabs():
            with gr.Tab("πŸ€– AI-Powered Strategy Report"):
                ai_report_output = gr.Markdown("### Your AI-generated report will appear here...")
            with gr.Tab("πŸ“‹ Data Profile"):
                profile_missing_df, profile_numeric_df, profile_categorical_df = gr.DataFrame(), gr.DataFrame(), gr.DataFrame()
            with gr.Tab("πŸ“Š Overview Visuals"):
                with gr.Row(): plot_types, plot_missing = gr.Plot(), gr.Plot()
                plot_correlation = gr.Plot()
            with gr.Tab("🎨 Interactive Explorer"):
                with gr.Row():
                    dd_hist_col = gr.Dropdown(label="Select Column for Histogram", interactive=True)
                    plot_histogram = gr.Plot()
                with gr.Row():
                    with gr.Column(scale=1):
                        dd_scatter_x, dd_scatter_y, dd_scatter_color = gr.Dropdown(label="X-Axis", interactive=True), gr.Dropdown(label="Y-Axis", interactive=True), gr.Dropdown(label="Color By", interactive=True)
                    with gr.Column(scale=2): plot_scatter = gr.Plot()
            with gr.Tab("🧩 Clustering (K-Means)", visible=False) as tab_cluster:
                with gr.Row():
                    with gr.Column(scale=1):
                        num_clusters = gr.Slider(minimum=2, maximum=10, value=3, step=1, label="K", interactive=True)
                        md_cluster_summary = gr.Markdown()
                    with gr.Column(scale=2): plot_cluster = gr.Plot()
                plot_elbow = gr.Plot()
            tab_timeseries, tab_text = gr.Tab("βŒ› Time-Series", visible=False), gr.Tab("πŸ“ Text", visible=False)

        # 2. DEFINE THE OUTPUTS LIST
        # This is the critical change. We create an explicit list of components
        # that will be updated by the main analysis function.
        # The order here MUST match the order of the returned tuple in the callback.
        main_outputs = [
            ai_report_output, profile_missing_df, profile_numeric_df, profile_categorical_df,
            plot_types, plot_missing, plot_correlation,
            dd_hist_col, dd_scatter_x, dd_scatter_y, dd_scatter_color,
            tab_timeseries, tab_text, tab_cluster
        ]

        # 3. REGISTER EVENT HANDLERS
        analysis_complete_event = analyze_button.click(
            fn=callbacks.run_initial_analysis,
            inputs=[upload_button],
            outputs=[state_analyzer]
        )
        analysis_complete_event.then(
            fn=callbacks.generate_reports_and_visuals,
            inputs=[state_analyzer],
            outputs=main_outputs  # Pass the LIST of components, not a dictionary.
        )

        # --- Other Interactive Callbacks ---
        dd_hist_col.change(fn=callbacks.create_histogram, inputs=[state_analyzer, dd_hist_col], outputs=[plot_histogram])
        scatter_inputs = [state_analyzer, dd_scatter_x, dd_scatter_y, dd_scatter_color]
        for dropdown in [dd_scatter_x, dd_scatter_y, dd_scatter_color]:
            dropdown.change(fn=callbacks.create_scatterplot, inputs=scatter_inputs, outputs=[plot_scatter])
        num_clusters.change(fn=callbacks.update_clustering, inputs=[state_analyzer, num_clusters], outputs=[plot_cluster, plot_elbow, md_cluster_summary])
    
    demo.launch(debug=False, server_name="0.0.0.0")

if __name__ == "__main__":
    main()