GuglielmoTor commited on
Commit
48a048c
·
verified ·
1 Parent(s): 8cf83ef

Update analytics_plot_generator.py

Browse files
Files changed (1) hide show
  1. analytics_plot_generator.py +131 -0
analytics_plot_generator.py CHANGED
@@ -7,6 +7,7 @@ import numpy as np
7
  import matplotlib.ticker as mticker
8
  import matplotlib.patches as patches # Added for rounded corners
9
  import ast # For safely evaluating string representations of lists
 
10
 
11
  # Configure logging for this module
12
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(module)s - %(message)s')
@@ -839,3 +840,133 @@ def generate_content_topic_breakdown_plot(df, topics_col='li_eb_labels', top_n=1
839
  logging.error(f"Error generating {title}: {e}", exc_info=True)
840
  if fig: plt.close(fig)
841
  return create_placeholder_plot(title=f"{title} Error", message=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import matplotlib.ticker as mticker
8
  import matplotlib.patches as patches # Added for rounded corners
9
  import ast # For safely evaluating string representations of lists
10
+ from analytics_data_processing import generate_chatbot_data_summaries
11
 
12
  # Configure logging for this module
13
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(module)s - %(message)s')
 
840
  logging.error(f"Error generating {title}: {e}", exc_info=True)
841
  if fig: plt.close(fig)
842
  return create_placeholder_plot(title=f"{title} Error", message=str(e))
843
+
844
+
845
+ # --- Analytics Tab: Plot Figure Generation Function ---
846
+ def update_analytics_plots_figures(token_state_value, date_filter_option, custom_start_date, custom_end_date, current_plot_configs):
847
+ logging.info(f"Updating analytics plot figures. Filter: {date_filter_option}, Custom Start: {custom_start_date}, Custom End: {custom_end_date}")
848
+ num_expected_plots = 19 # Ensure this matches the number of plots generated
849
+
850
+ plot_data_summaries_for_chatbot = {} # Initialize dict for chatbot summaries
851
+
852
+ if not token_state_value or not token_state_value.get("token"):
853
+ message = "❌ Accesso negato. Nessun token. Impossibile generare le analisi."
854
+ logging.warning(message)
855
+ placeholder_figs = [create_placeholder_plot(title="Accesso Negato", message="Nessun token.") for _ in range(num_expected_plots)]
856
+ # For each plot_config, add a default "no data" summary
857
+ for p_cfg in current_plot_configs:
858
+ plot_data_summaries_for_chatbot[p_cfg["id"]] = "Accesso negato, nessun dato per il chatbot."
859
+ return [message] + placeholder_figs + [plot_data_summaries_for_chatbot]
860
+ try:
861
+ (filtered_merged_posts_df,
862
+ filtered_mentions_df,
863
+ date_filtered_follower_stats_df, # For time-based follower plots
864
+ raw_follower_stats_df, # For demographic follower plots
865
+ start_dt_for_msg, end_dt_for_msg) = \
866
+ prepare_filtered_analytics_data(
867
+ token_state_value, date_filter_option, custom_start_date, custom_end_date
868
+ )
869
+
870
+ # Generate data summaries for chatbot AFTER data preparation
871
+ plot_data_summaries_for_chatbot = generate_chatbot_data_summaries(
872
+ current_plot_configs, # Pass the plot_configs list
873
+ filtered_merged_posts_df,
874
+ filtered_mentions_df,
875
+ date_filtered_follower_stats_df,
876
+ raw_follower_stats_df,
877
+ token_state_value
878
+ )
879
+
880
+ except Exception as e:
881
+ error_msg = f"❌ Errore durante la preparazione dei dati per le analisi: {e}"
882
+ logging.error(error_msg, exc_info=True)
883
+ placeholder_figs = [create_placeholder_plot(title="Errore Preparazione Dati", message=str(e)) for _ in range(num_expected_plots)]
884
+ for p_cfg in current_plot_configs:
885
+ plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore preparazione dati: {e}"
886
+ return [error_msg] + placeholder_figs + [plot_data_summaries_for_chatbot]
887
+
888
+ date_column_posts = token_state_value.get("config_date_col_posts", "published_at")
889
+ date_column_mentions = token_state_value.get("config_date_col_mentions", "date")
890
+ media_type_col_name = token_state_value.get("config_media_type_col", "media_type")
891
+ eb_labels_col_name = token_state_value.get("config_eb_labels_col", "li_eb_label")
892
+
893
+ plot_figs = [] # Initialize list to hold plot figures
894
+
895
+ plot_titles_for_errors = [p_cfg["label"] for p_cfg in current_plot_configs]
896
+
897
+ try:
898
+ # Dinamiche dei Follower (2 plots)
899
+ plot_figs.append(generate_followers_count_over_time_plot(date_filtered_follower_stats_df, type_value='follower_gains_monthly'))
900
+ 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
901
+
902
+ # Demografia Follower (4 plots)
903
+ plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_geo', plot_title="Follower per Località"))
904
+ plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_function', plot_title="Follower per Ruolo"))
905
+ plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_industry', plot_title="Follower per Settore"))
906
+ plot_figs.append(generate_followers_by_demographics_plot(raw_follower_stats_df, type_value='follower_seniority', plot_title="Follower per Anzianità"))
907
+
908
+ # Approfondimenti Performance Post (4 plots)
909
+ plot_figs.append(generate_engagement_rate_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
910
+ plot_figs.append(generate_reach_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
911
+ 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
912
+ plot_figs.append(generate_likes_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
913
+
914
+ # Engagement Dettagliato Post nel Tempo (4 plots)
915
+ plot_figs.append(generate_clicks_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
916
+ plot_figs.append(generate_shares_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
917
+ plot_figs.append(generate_comments_over_time_plot(filtered_merged_posts_df, date_column=date_column_posts))
918
+ plot_figs.append(generate_comments_sentiment_breakdown_plot(filtered_merged_posts_df, sentiment_column='comment_sentiment')) # Make sure 'comment_sentiment' exists
919
+
920
+ # Analisi Strategia Contenuti (3 plots)
921
+ plot_figs.append(generate_post_frequency_plot(filtered_merged_posts_df, date_column=date_column_posts))
922
+ plot_figs.append(generate_content_format_breakdown_plot(filtered_merged_posts_df, format_col=media_type_col_name))
923
+ plot_figs.append(generate_content_topic_breakdown_plot(filtered_merged_posts_df, topics_col=eb_labels_col_name))
924
+
925
+ # Analisi Menzioni (Dettaglio) (2 plots)
926
+ plot_figs.append(generate_mentions_activity_plot(filtered_mentions_df, date_column=date_column_mentions))
927
+ plot_figs.append(generate_mention_sentiment_plot(filtered_mentions_df)) # Make sure this function handles empty/malformed df
928
+
929
+ if len(plot_figs) != num_expected_plots:
930
+ logging.warning(f"Mismatch in generated plots. Expected {num_expected_plots}, got {len(plot_figs)}. This will cause UI update issues.")
931
+ while len(plot_figs) < num_expected_plots:
932
+ plot_figs.append(create_placeholder_plot(title="Grafico Non Generato", message="Logica di generazione incompleta."))
933
+
934
+ message = f"📊 Analisi aggiornate per il periodo: {date_filter_option}"
935
+ if date_filter_option == "Intervallo Personalizzato":
936
+ s_display = start_dt_for_msg.strftime('%Y-%m-%d') if start_dt_for_msg else "Qualsiasi"
937
+ e_display = end_dt_for_msg.strftime('%Y-%m-%d') if end_dt_for_msg else "Qualsiasi"
938
+ message += f" (Da: {s_display} A: {e_display})"
939
+
940
+ final_plot_figs = []
941
+ for i, p_fig_candidate in enumerate(plot_figs):
942
+ if p_fig_candidate is not None and not isinstance(p_fig_candidate, str): # Basic check for a plot object
943
+ final_plot_figs.append(p_fig_candidate)
944
+ else:
945
+ err_title = plot_titles_for_errors[i] if i < len(plot_titles_for_errors) else f"Grafico {i+1}"
946
+ logging.warning(f"Plot {err_title} (index {i}) non è una figura valida: {p_fig_candidate}. Uso placeholder.")
947
+ final_plot_figs.append(create_placeholder_plot(title=f"Errore: {err_title}", message="Impossibile generare figura."))
948
+
949
+ return [message] + final_plot_figs[:num_expected_plots] + [plot_data_summaries_for_chatbot]
950
+
951
+ except (KeyError, ValueError) as e_plot_data:
952
+ logging.error(f"Errore dati durante la generazione di un grafico specifico: {e_plot_data}", exc_info=True)
953
+ error_msg_display = f"Errore dati in un grafico: {str(e_plot_data)[:100]}"
954
+
955
+ num_already_generated = len(plot_figs)
956
+ for i in range(num_already_generated, num_expected_plots):
957
+ err_title_fill = plot_titles_for_errors[i] if i < len(plot_titles_for_errors) else f"Grafico {i+1}"
958
+ plot_figs.append(create_placeholder_plot(title=f"Errore Dati: {err_title_fill}", message=f"Precedente errore: {str(e_plot_data)[:50]}"))
959
+
960
+ for p_cfg in current_plot_configs: # Ensure summaries dict is populated on error
961
+ if p_cfg["id"] not in plot_data_summaries_for_chatbot:
962
+ plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore dati grafico: {e_plot_data}"
963
+ return [error_msg_display] + plot_figs[:num_expected_plots] + [plot_data_summaries_for_chatbot]
964
+
965
+ except Exception as e_general:
966
+ error_msg = f"❌ Errore generale durante la generazione dei grafici: {e_general}"
967
+ logging.error(error_msg, exc_info=True)
968
+ 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)]
969
+ for p_cfg in current_plot_configs: # Ensure summaries dict is populated on error
970
+ if p_cfg["id"] not in plot_data_summaries_for_chatbot:
971
+ plot_data_summaries_for_chatbot[p_cfg["id"]] = f"Errore generale grafici: {e_general}"
972
+ return [error_msg] + placeholder_figs_general + [plot_data_summaries_for_chatbot]