Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -26,26 +26,8 @@ from ui_generators import (
|
|
26 |
build_analytics_tab_plot_area,
|
27 |
BOMB_ICON, EXPLORE_ICON, FORMULA_ICON, ACTIVE_ICON
|
28 |
)
|
29 |
-
from analytics_data_processing import prepare_filtered_analytics_data
|
30 |
-
from analytics_plot_generator import
|
31 |
-
generate_posts_activity_plot,
|
32 |
-
generate_mentions_activity_plot, generate_mention_sentiment_plot,
|
33 |
-
generate_followers_count_over_time_plot,
|
34 |
-
generate_followers_growth_rate_plot,
|
35 |
-
generate_followers_by_demographics_plot,
|
36 |
-
generate_engagement_rate_over_time_plot,
|
37 |
-
generate_reach_over_time_plot,
|
38 |
-
generate_impressions_over_time_plot,
|
39 |
-
create_placeholder_plot,
|
40 |
-
generate_likes_over_time_plot,
|
41 |
-
generate_clicks_over_time_plot,
|
42 |
-
generate_shares_over_time_plot,
|
43 |
-
generate_comments_over_time_plot,
|
44 |
-
generate_comments_sentiment_breakdown_plot,
|
45 |
-
generate_post_frequency_plot,
|
46 |
-
generate_content_format_breakdown_plot,
|
47 |
-
generate_content_topic_breakdown_plot
|
48 |
-
)
|
49 |
from formulas import PLOT_FORMULAS
|
50 |
|
51 |
# --- NEW CHATBOT MODULE IMPORTS ---
|
@@ -83,135 +65,6 @@ PLOT_ID_TO_FORMULA_KEY_MAP = {
|
|
83 |
}
|
84 |
|
85 |
|
86 |
-
# --- Analytics Tab: Plot Figure Generation Function ---
|
87 |
-
def update_analytics_plots_figures(token_state_value, date_filter_option, custom_start_date, custom_end_date, current_plot_configs):
|
88 |
-
logging.info(f"Updating analytics plot figures. Filter: {date_filter_option}, Custom Start: {custom_start_date}, Custom End: {custom_end_date}")
|
89 |
-
num_expected_plots = 19 # Ensure this matches the number of plots generated
|
90 |
-
|
91 |
-
plot_data_summaries_for_chatbot = {} # Initialize dict for chatbot summaries
|
92 |
-
|
93 |
-
if not token_state_value or not token_state_value.get("token"):
|
94 |
-
message = "❌ Accesso negato. Nessun token. Impossibile generare le analisi."
|
95 |
-
logging.warning(message)
|
96 |
-
placeholder_figs = [create_placeholder_plot(title="Accesso Negato", message="Nessun token.") for _ in range(num_expected_plots)]
|
97 |
-
# For each plot_config, add a default "no data" summary
|
98 |
-
for p_cfg in current_plot_configs:
|
99 |
-
plot_data_summaries_for_chatbot[p_cfg["id"]] = "Accesso negato, nessun dato per il chatbot."
|
100 |
-
return [message] + placeholder_figs + [plot_data_summaries_for_chatbot]
|
101 |
-
try:
|
102 |
-
(filtered_merged_posts_df,
|
103 |
-
filtered_mentions_df,
|
104 |
-
date_filtered_follower_stats_df, # For time-based follower plots
|
105 |
-
raw_follower_stats_df, # For demographic follower plots
|
106 |
-
start_dt_for_msg, end_dt_for_msg) = \
|
107 |
-
prepare_filtered_analytics_data(
|
108 |
-
token_state_value, date_filter_option, custom_start_date, custom_end_date
|
109 |
-
)
|
110 |
-
|
111 |
-
# Generate data summaries for chatbot AFTER data preparation
|
112 |
-
plot_data_summaries_for_chatbot = generate_chatbot_data_summaries(
|
113 |
-
current_plot_configs, # Pass the plot_configs list
|
114 |
-
filtered_merged_posts_df,
|
115 |
-
filtered_mentions_df,
|
116 |
-
date_filtered_follower_stats_df,
|
117 |
-
raw_follower_stats_df,
|
118 |
-
token_state_value
|
119 |
-
)
|
120 |
-
|
121 |
-
except Exception as e:
|
122 |
-
error_msg = f"❌ Errore durante la preparazione dei dati per le analisi: {e}"
|
123 |
-
logging.error(error_msg, exc_info=True)
|
124 |
-
placeholder_figs = [create_placeholder_plot(title="Errore Preparazione Dati", message=str(e)) for _ in range(num_expected_plots)]
|
125 |
-
for p_cfg in current_plot_configs:
|
126 |
-
plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore preparazione dati: {e}"
|
127 |
-
return [error_msg] + placeholder_figs + [plot_data_summaries_for_chatbot]
|
128 |
-
|
129 |
-
date_column_posts = token_state_value.get("config_date_col_posts", "published_at")
|
130 |
-
date_column_mentions = token_state_value.get("config_date_col_mentions", "date")
|
131 |
-
media_type_col_name = token_state_value.get("config_media_type_col", "media_type")
|
132 |
-
eb_labels_col_name = token_state_value.get("config_eb_labels_col", "li_eb_label")
|
133 |
-
|
134 |
-
plot_figs = [] # Initialize list to hold plot figures
|
135 |
-
|
136 |
-
plot_titles_for_errors = [p_cfg["label"] for p_cfg in current_plot_configs]
|
137 |
-
|
138 |
-
try:
|
139 |
-
# Dinamiche dei Follower (2 plots)
|
140 |
-
plot_figs.append(generate_followers_count_over_time_plot(date_filtered_follower_stats_df, type_value='follower_gains_monthly'))
|
141 |
-
plot_figs.append(generate_followers_growth_rate_plot(date_filtered_follower_stats_df, type_value='follower_gains_monthly')) # Assuming this uses 'follower_gains_monthly' to calculate rate
|
142 |
-
|
143 |
-
# Demografia Follower (4 plots)
|
144 |
-
plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_geo', plot_title="Follower per Località"))
|
145 |
-
plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_function', plot_title="Follower per Ruolo"))
|
146 |
-
plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_industry', plot_title="Follower per Settore"))
|
147 |
-
plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_seniority', plot_title="Follower per Anzianità"))
|
148 |
-
|
149 |
-
# Approfondimenti Performance Post (4 plots)
|
150 |
-
plot_figs.append(generate_engagement_rate_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
151 |
-
plot_figs.append(generate_reach_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
152 |
-
plot_figs.append(generate_impressions_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts)) # Ensure 'impressions_sum' or equivalent is used by this func
|
153 |
-
plot_figs.append(generate_likes_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
154 |
-
|
155 |
-
# Engagement Dettagliato Post nel Tempo (4 plots)
|
156 |
-
plot_figs.append(generate_clicks_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
157 |
-
plot_figs.append(generate_shares_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
158 |
-
plot_figs.append(generate_comments_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
159 |
-
plot_figs.append(generate_comments_sentiment_breakdown_plot(filtered_merged_posts_df, sentiment_column='comment_sentiment')) # Make sure 'comment_sentiment' exists
|
160 |
-
|
161 |
-
# Analisi Strategia Contenuti (3 plots)
|
162 |
-
plot_figs.append(generate_post_frequency_plot(filtered_merged_posts_df, date_column=date_column_posts))
|
163 |
-
plot_figs.append(generate_content_format_breakdown_plot(filtered_merged_posts_df, format_col=media_type_col_name))
|
164 |
-
plot_figs.append(generate_content_topic_breakdown_plot(filtered_merged_posts_df, topics_col=eb_labels_col_name))
|
165 |
-
|
166 |
-
# Analisi Menzioni (Dettaglio) (2 plots)
|
167 |
-
plot_figs.append(generate_mentions_activity_plot(filtered_mentions_df, date_column=date_column_mentions))
|
168 |
-
plot_figs.append(generate_mention_sentiment_plot(filtered_mentions_df)) # Make sure this function handles empty/malformed df
|
169 |
-
|
170 |
-
if len(plot_figs) != num_expected_plots:
|
171 |
-
logging.warning(f"Mismatch in generated plots. Expected {num_expected_plots}, got {len(plot_figs)}. This will cause UI update issues.")
|
172 |
-
while len(plot_figs) < num_expected_plots:
|
173 |
-
plot_figs.append(create_placeholder_plot(title="Grafico Non Generato", message="Logica di generazione incompleta."))
|
174 |
-
|
175 |
-
message = f"📊 Analisi aggiornate per il periodo: {date_filter_option}"
|
176 |
-
if date_filter_option == "Intervallo Personalizzato":
|
177 |
-
s_display = start_dt_for_msg.strftime('%Y-%m-%d') if start_dt_for_msg else "Qualsiasi"
|
178 |
-
e_display = end_dt_for_msg.strftime('%Y-%m-%d') if end_dt_for_msg else "Qualsiasi"
|
179 |
-
message += f" (Da: {s_display} A: {e_display})"
|
180 |
-
|
181 |
-
final_plot_figs = []
|
182 |
-
for i, p_fig_candidate in enumerate(plot_figs):
|
183 |
-
if p_fig_candidate is not None and not isinstance(p_fig_candidate, str): # Basic check for a plot object
|
184 |
-
final_plot_figs.append(p_fig_candidate)
|
185 |
-
else:
|
186 |
-
err_title = plot_titles_for_errors[i] if i < len(plot_titles_for_errors) else f"Grafico {i+1}"
|
187 |
-
logging.warning(f"Plot {err_title} (index {i}) non è una figura valida: {p_fig_candidate}. Uso placeholder.")
|
188 |
-
final_plot_figs.append(create_placeholder_plot(title=f"Errore: {err_title}", message="Impossibile generare figura."))
|
189 |
-
|
190 |
-
return [message] + final_plot_figs[:num_expected_plots] + [plot_data_summaries_for_chatbot]
|
191 |
-
|
192 |
-
except (KeyError, ValueError) as e_plot_data:
|
193 |
-
logging.error(f"Errore dati durante la generazione di un grafico specifico: {e_plot_data}", exc_info=True)
|
194 |
-
error_msg_display = f"Errore dati in un grafico: {str(e_plot_data)[:100]}"
|
195 |
-
|
196 |
-
num_already_generated = len(plot_figs)
|
197 |
-
for i in range(num_already_generated, num_expected_plots):
|
198 |
-
err_title_fill = plot_titles_for_errors[i] if i < len(plot_titles_for_errors) else f"Grafico {i+1}"
|
199 |
-
plot_figs.append(create_placeholder_plot(title=f"Errore Dati: {err_title_fill}", message=f"Precedente errore: {str(e_plot_data)[:50]}"))
|
200 |
-
|
201 |
-
for p_cfg in current_plot_configs: # Ensure summaries dict is populated on error
|
202 |
-
if p_cfg["id"] not in plot_data_summaries_for_chatbot:
|
203 |
-
plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore dati grafico: {e_plot_data}"
|
204 |
-
return [error_msg_display] + plot_figs[:num_expected_plots] + [plot_data_summaries_for_chatbot]
|
205 |
-
|
206 |
-
except Exception as e_general:
|
207 |
-
error_msg = f"❌ Errore generale durante la generazione dei grafici: {e_general}"
|
208 |
-
logging.error(error_msg, exc_info=True)
|
209 |
-
placeholder_figs_general = [create_placeholder_plot(title=plot_titles_for_errors[i] if i < len(plot_titles_for_errors) else f"Grafico {i+1}", message=str(e_general)) for i in range(num_expected_plots)]
|
210 |
-
for p_cfg in current_plot_configs: # Ensure summaries dict is populated on error
|
211 |
-
if p_cfg["id"] not in plot_data_summaries_for_chatbot:
|
212 |
-
plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore generale grafici: {e_general}"
|
213 |
-
return [error_msg] + placeholder_figs_general + [plot_data_summaries_for_chatbot]
|
214 |
-
|
215 |
|
216 |
# --- Gradio UI Blocks ---
|
217 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|
|
|
26 |
build_analytics_tab_plot_area,
|
27 |
BOMB_ICON, EXPLORE_ICON, FORMULA_ICON, ACTIVE_ICON
|
28 |
)
|
29 |
+
from analytics_data_processing import prepare_filtered_analytics_data # This is key for data structure
|
30 |
+
from analytics_plot_generator import update_analytics_plots_figures
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
from formulas import PLOT_FORMULAS
|
32 |
|
33 |
# --- NEW CHATBOT MODULE IMPORTS ---
|
|
|
65 |
}
|
66 |
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
# --- Gradio UI Blocks ---
|
70 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
|