Advertisement
Python253

Trend_AV

Apr 6th, 2024
594
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 48.14 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Filename: Trend_AV.py
  4. # Version: 1.27
  5. # Author: Jeoi Reqi
  6. # Date: February 2024
  7.  
  8. '''
  9. [DESCRIPTION]:
  10. Trend_AV is a Python script designed to analyze and visualize Google Trends data using the Google Trends API. It facilitates the exploration of interest trends over time for user-specified topics. The script offers the following functionalities:
  11.  
  12. 1. Line Plots: Generates monthly-separated line plots with solid markers, depicting the trend of interest over time.
  13.  
  14. 2. 3D Bar Plots: Creates visualizations illustrating interest levels for specified topics over time using 3D bar plots.
  15.  
  16. 3. Pie Charts: Generates pie charts with average values, providing insights into the distribution of interest across different topics.
  17.  
  18. 4. Scatter Plots: Displays scatter plots with average values, showing the relationship between time and interest level for specified topics.
  19.  
  20. 5. Stack Plots: Generates stack plots illustrating the contribution of each topic to the overall interest level over time.
  21.  
  22. 6. Word Clouds: Utilizes related top and rising topics fetched from Google Trends to generate word clouds, offering a visually appealing representation of related queries.
  23.  
  24. [REQUIRED FILES]:
  25. - header.txt:       Contains header information for the script.
  26.                    URL: https://pastebin.com/PhGW7s6i
  27.  
  28. - about.py:         Provides information about the script and its functionalities.
  29.                    URL: https://pastebin.com/14xC5Mji
  30.  
  31. - promo.txt:        Contains promotional content for the script.
  32.                    URL: https://pastebin.com/xkedg3n5
  33.  
  34. - requirements.txt: Lists the required dependencies for running the script.
  35.                    URL: https://pastebin.com/wutgrtpn
  36.  
  37. [NOTE]:
  38. Ensure that all required files are saved in the current working directory with the correct file extensions.
  39.  
  40. '''
  41.  
  42.  
  43.  
  44. # GET IMPORTS
  45. import sys
  46. import subprocess
  47. import importlib
  48. import numpy as np
  49. import warnings
  50. import matplotlib.pyplot as plt
  51. import matplotlib.animation as animation
  52. import matplotlib.lines as mlines
  53. from matplotlib.lines import Line2D
  54. from mpl_toolkits.mplot3d.art3d import Poly3DCollection
  55. from mpl_toolkits.mplot3d import Axes3D
  56. from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
  57. from pytrends.request import TrendReq
  58. from dateutil.relativedelta import relativedelta
  59. from typing import List
  60. from datetime import datetime
  61. from wordcloud import WordCloud
  62.  
  63. # INSTALLATIONS
  64. def import_module_or_install(package_name):
  65.     try:
  66.         return importlib.import_module(package_name)
  67.     except ImportError:
  68.         print(f"Error: {package_name} module not found. Installing...")
  69.         subprocess.run([sys.executable, "-m", "pip", "install", package_name], check=True)
  70.         print(f"Successfully installed {package_name}.")
  71.         return importlib.import_module(package_name)
  72.  
  73. # Try importing these libraries or install them if not found
  74. pytrends = import_module_or_install('pytrends')
  75. plt = import_module_or_install('matplotlib.pyplot')
  76. np = import_module_or_install('numpy')
  77.  
  78. # CLEAR SCREEN
  79. def wipe():
  80.     print('\n' * 100)
  81.  
  82. # INSTALL PACKAGES
  83. def install_packages(packages):
  84.     try:
  85.         for package in packages:
  86.             if not isinstance(package, str):
  87.                 raise ValueError(f"Package name must be a string, but found: {package}")
  88.            
  89.             # Suppress output during installation for python-dateutil
  90.             stdout_arg = subprocess.PIPE if package == 'python-dateutil' else sys.stdout
  91.             stderr_arg = subprocess.PIPE if package == 'python-dateutil' else sys.stderr
  92.             subprocess.run([sys.executable, "-m", "pip", "install", package], check=True, stdout=stdout_arg, stderr=stderr_arg)
  93.     except subprocess.CalledProcessError as e:
  94.         print(f"Error: Failed to install packages. Please install them manually.\n")
  95.         sys.exit(1)
  96.  
  97. if __name__ == "__main__":
  98.     print("\nChecking and installing required packages...\n")
  99.  
  100.     # Check if python-dateutil is installed
  101.     python_dateutil_installed = importlib.util.find_spec('dateutil') is not None
  102.  
  103.     if not python_dateutil_installed:
  104.         print("Installing python-dateutil...")
  105.         install_packages(['python-dateutil'])
  106.         print("\npython-dateutil installed successfully.\n\n\n\n")
  107.         wipe()
  108.     else:
  109.         print("\nAll requirements have been satisfied.\n\n\n\n")
  110.         input("\n\nPress [ENTER] to continue.\n")
  111.         wipe()
  112.  
  113.     warnings.simplefilter(action='ignore', category=FutureWarning)
  114.  
  115.     # Now you should be able to use TrendReq
  116.     pytrends = TrendReq(hl='en-US', tz=-480)
  117.  
  118.  
  119. '''                    [GLOBAL HEADER]'''
  120.  
  121. # Read the content of header.txt
  122. with open('header.txt', 'r', encoding='utf-8') as file:
  123.     header_content = file.read()
  124.  
  125. def header():  # Function to print the header
  126.     wipe()
  127.     print(header_content)
  128.  
  129. header()  # Call the header function
  130.  
  131.  
  132. '''                    [GLOBAL VARIABLES & CONSTANTS]'''
  133.  
  134. # User Input for Topics and Timeframe
  135. interest_over_time = None  # Initialize interest_over_time as a global variable
  136. num_months = None  # Initialize num_months as a global variable
  137.  
  138. # Initialize global Keywords list
  139. keywords: list[str] = []
  140.  
  141. # Set the constant max values for topics & results
  142. max_topics = 5
  143. max_top = 24
  144. max_rising = 24
  145. max_months = 240
  146.  
  147. # For use with 3D Bar Plot (Bar Sizes: Eg; 70% width/40% depth)
  148. bar_width = 0.70  # Width on the x-axis as a percent Using dx
  149. bar_depth = 0.40  # Width on the x-axis as a percent Using dx
  150.  
  151. '''                    [SYSTEM FUNCTIONS]'''
  152.  
  153.  
  154. # Define the reset program function
  155. def reset_program():
  156.     global keywords
  157.     global related_data_displayed
  158.    
  159.     # Clear user inputs and related data
  160.     keywords = []
  161.     related_data_displayed = False
  162.    
  163.     print("\nProgram reset. All data cleared.\n")
  164.     input("Press [ENTER] to continue.")
  165.  
  166.     # Call the user_input function to get user input
  167.     user_input()
  168.  
  169. # Flag to track if related data has been displayed
  170. related_data_displayed = False
  171.  
  172.  
  173. '''                [USER INPUT]'''
  174.  
  175. '''
  176.    THIS IS AN INTERACTIVE FUNCTION TO GATHER USER INPUT FOR TOPICS AND TIMEFRAME.
  177. '''
  178.  
  179. # Function to get user input for topics
  180. def user_input():
  181.     global interest_over_time  # Declare interest_over_time as a global variable
  182.     global num_months  # Declare num_months as a global variable
  183.    
  184.     # User Input for Topics
  185.     while len(keywords) < 1 or len(keywords) > max_topics:
  186.         try:
  187.             # Prompt user for the number of topics they want to analyze
  188.             num_topics = int(input(f"\nEnter the number of topics (1 to {max_topics}): "))
  189.             # Validate user input to ensure it falls within the specified range
  190.             if 1 <= num_topics <= max_topics:
  191.                 for i in range(num_topics):
  192.                     keyword = input(f"Enter topic/query {i + 1}: ")
  193.                     keywords.append(keyword.lower())  # Automatically convert to lowercase
  194.             else:
  195.                 # Display an error message for an invalid number of topics
  196.                 print(f"\nInvalid number of topics. Please enter a number between 1 and {max_topics}.\n")
  197.         except ValueError:
  198.             # Handle the case where the user enters a non-integer value
  199.             print("\nInvalid input. Please enter a valid number.\n")
  200.  
  201.     # User Input for Timeframe
  202.     while True:
  203.         try:
  204.             # Prompt user for the number of months to display in the analysis
  205.             num_months = int(input(f"\nEnter the number of months to display between this month (1) and 2004 ({max_months}): "))
  206.             # Validate user input for the timeframe
  207.             if 1 <= num_months <= max_months:
  208.                 # Calculate the end date
  209.                 end_date = datetime.today().strftime('%Y-%m-%d')
  210.                 # Calculate the start date based on the number of months
  211.                 start_date = (datetime.today() - relativedelta(months=num_months)).strftime('%Y-%m-%d')
  212.  
  213.                 # Fetch data from Google Trends based on user-specified topics & timeframe
  214.                 timeframe = f'{start_date} {end_date}'
  215.                 print(f"\nFetching data from Google Trends with timeframe: {timeframe}\n")
  216.                
  217.                 pytrends.build_payload(keywords, timeframe=timeframe)
  218.                 interest_over_time = pytrends.interest_over_time()
  219.                
  220.                 # Wait for the user to hit [ENTER] to continue to the Menu
  221.                 input("\nPress [ENTER] to continue to the main menu.\n")
  222.                
  223.                 if interest_over_time.empty:
  224.                     raise ValueError("No data retrieved from Google Trends.")
  225.                
  226.                 break  # Exit the loop if input is valid
  227.             else:
  228.                 # Display an error message for an invalid number of months
  229.                 print(f"\nInvalid number of months. Please enter a number between 1 and {max_months}.\n")
  230.         except ValueError as ve:
  231.             print(f"\nError: {ve}\n")
  232.  
  233. # Call the user_input function to get user input
  234. user_input()
  235.  
  236.  
  237. '''                    [GENERATE THE PLOTS]'''
  238.  
  239. '''
  240.    [GENERATE THE PLOTS]:
  241.    THIS SECTION OF THE CODE CONTAINS THE FUNCTIONS TO GENERATE & VISUALIZE VARIOUS TYPES OF PLOTS BASED ON
  242.    GOOGLE TRENDS DATA. EACH FUNCTION IS DESIGNED TO PRESENT DIFFERENT INSIGHTS INTO THE INTEREST OVER TIME
  243.    FOR USER-SPECIFIED TOPICS OR QUERIES. THE PLOTS INCLUDE ANIMATED AND STATIC VERSIONS OF LINE PLOTS,
  244.    BAR PLOTS (2D AND 3D), PIE CHARTS, SCATTER PLOTS, AND STACK PLOTS. THE USER CAN CHOOSE TO DISPLAY THESE
  245.    PLOTS INDIVIDUALLY OR IN COMBINATIONS. THE FUNCTIONS PROVIDE INTERACTIVE AND DYNAMIC VISUALIZATIONS,
  246.    ALLOWING USERS TO EXPLORE TRENDS, COMPARE TOPICS, AND UNDERSTAND THE RELATIVE STRENGTH AND INTEREST
  247.    PATTERNS OVER SPECIFIED TIMEFRAMES.
  248. '''
  249.  
  250. '''                    [LINE PLOTS]'''
  251.  
  252. # ANIMATED LINE PLOT
  253. def animate_line_plot(interest_over_time, keywords, num_months):
  254.     '''
  255.        GENERATE AND DISPLAY ANIMATED LINE PLOTS WITH SOLID MARKERS.
  256.  
  257.        PARAMETERS:
  258.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  259.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  260.        - NUM_MONTHS (INT): NUMBER OF MONTHS FOR THE PLOT.
  261.    '''
  262.     print("\nAnimating line plots with solid markers...")
  263.  
  264.     fig, ax = plt.subplots(figsize=(16, 8))
  265.  
  266.     def update(frame):
  267.         ax.clear()
  268.  
  269.         # Calculate the percentage of completion
  270.         percent_complete = (frame + 1) / total_frames * 100
  271.  
  272.         for keyword in keywords:
  273.             # Plot the line for the current frame with hollow markers
  274.             end_index = frame * len(interest_over_time) // total_frames
  275.             ax.plot(interest_over_time.index[:end_index + 1], interest_over_time[keyword][:end_index + 1],
  276.                     label=keyword, marker='o', markersize=8, linestyle='solid', mec='none')
  277.  
  278.         ax.set_title(f'Animated Line Plot\n{percent_complete:.2f}% Complete')
  279.         ax.set_xlabel('Date')
  280.         ax.set_ylabel('Interest Level')
  281.         ax.legend(loc='upper left')
  282.  
  283.         # Set y-axis ticks from 0 to 100 in increments of 10
  284.         ax.set_yticks(np.arange(0, 110, 10))
  285.         # Set the fixed height for the y-axis
  286.         ax.set_ylim(0, 100)
  287.  
  288.     # Calculate total frames
  289.     total_frames = len(interest_over_time)
  290.  
  291.     # Create the animation
  292.     animation_line_plots = animation.FuncAnimation(fig, update, frames=total_frames, interval=250, repeat=False)
  293.  
  294.     plt.show()
  295.  
  296.  
  297. # GENERATE LINE PLOT
  298. def generate_line_plot(interest_over_time, keywords, num_months):
  299.     '''
  300.        GENERATE AND DISPLAY LINE PLOTS WITH SOLID MARKERS.
  301.  
  302.        PARAMETERS:
  303.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  304.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  305.        - NUM_MONTHS (INT): NUMBER OF MONTHS FOR THE PLOT.
  306.    '''
  307.     print("\nGenerating line plots with solid markers...")
  308.  
  309.     plt.figure(figsize=(16, 8))
  310.  
  311.     for keyword in keywords:
  312.         # Plot the line with hollow markers
  313.         plt.plot(interest_over_time.index, interest_over_time[keyword], label=keyword, marker='o', markersize=8,
  314.                  linestyle='solid', mec='none')
  315.  
  316.     plt.title(f'Static Line Plot')
  317.     plt.xlabel('Date')
  318.     plt.ylabel('Interest Level')
  319.     plt.legend(loc='upper left')
  320.  
  321.     # Set y-axis ticks from 0 to 100 in increments of 10
  322.     plt.yticks(np.arange(0, 110, 10))
  323.  
  324.     # Set the fixed height for the y-axis
  325.     plt.ylim(0, 100)
  326.  
  327.     plt.show()
  328.  
  329.  
  330. '''                    [BAR PLOTS]'''
  331.  
  332. # ANIMATE 2D BAR PLOT
  333. def animate_2d_bar_plot(interest_over_time, keywords):
  334.     """
  335.    Generate and display an animated 2D bar plot.
  336.  
  337.    Parameters:
  338.    - interest_over_time (DataFrame): Dataframe containing interest over time.
  339.    - keywords (List[str]): List of keywords to plot.
  340.    """
  341.     global num_months  # Declare num_months as a global variable
  342.     print("\nAnimating 2D Bar Plot...")
  343.  
  344.     fig, ax = plt.subplots(figsize=(8, 8))
  345.     colors = plt.cm.viridis(np.linspace(0, 1, len(keywords)))
  346.  
  347.     # Sort keywords based on their mean values
  348.     sorted_keywords = sorted(keywords, key=lambda keyword: interest_over_time[keyword].mean())
  349.  
  350.     def update(frame):
  351.         ax.clear()
  352.  
  353.         # Calculate the percentage completed
  354.         percent_complete = (frame + 1) / total_frames * 100
  355.  
  356.         # Extract data for the current frame
  357.         start_index = frame * len(interest_over_time) // num_months
  358.         end_index = (frame + 1) * len(interest_over_time) // num_months
  359.         ys = interest_over_time.iloc[start_index:end_index][sorted_keywords]
  360.  
  361.         # Plot the 2D bar chart for the current frame
  362.         bars = ax.bar(sorted_keywords, ys.mean(), color=colors)
  363.  
  364.         # Dynamically display the current month number
  365.         current_month = frame + 1
  366.         ax.set_title(f'Animated 2D Bar Plot - Month {current_month} / {num_months}\n({percent_complete:.1f}% Complete)', fontsize=14, fontweight='bold')
  367.         ax.set_ylabel('Interest Level')
  368.  
  369.         # Annotate each bar with its value
  370.         for bar, y in zip(bars, ys.mean()):
  371.             height = bar.get_height()
  372.             ax.annotate(f'{y:.2f}', xy=(bar.get_x() + bar.get_width() / 2, height),
  373.                         xytext=(0, 3), textcoords='offset points',
  374.                         ha='center', va='bottom')
  375.  
  376.         # Set x-axis ticks and labels based on sorted keywords
  377.         ax.set_xticks(np.arange(len(sorted_keywords)))
  378.         ax.set_xticklabels(sorted_keywords, rotation=45, ha='right')  # Adjust rotation and alignment as needed
  379.  
  380.         # Set y-axis ticks from 0 to 100 in increments of 10
  381.         ax.set_yticks(np.arange(0, 110, 10))
  382.  
  383.         # Set the fixed height for the y-axis
  384.         ax.set_ylim(0, 100)
  385.  
  386.     # Calculate total frames
  387.     total_frames = min(len(interest_over_time), num_months)
  388.  
  389.     # Create the animation
  390.     animation_2d_bar = animation.FuncAnimation(fig, update, frames=total_frames, interval=250, repeat=False)
  391.  
  392.     plt.show()
  393.  
  394.  
  395.  
  396. # ANIMATE 3D BAR PLOT  
  397. def animate_3d_bar_plot(interest_over_time, keywords, num_months=num_months):
  398.     """
  399.    Generate and display an animated 3D bar plot.
  400.  
  401.    Parameters:
  402.    - interest_over_time (DataFrame): Dataframe containing interest over time.
  403.    - keywords (List[str]): List of keywords to plot.
  404.    - num_months (int): Number of months to display in the animation.
  405.    """
  406.     print("\nAnimating 3D Bar Plot...")
  407.  
  408.     fig = plt.figure(figsize=(8, 8))
  409.     ax = fig.add_subplot(projection='3d')
  410.  
  411.     # Set figure elevation, azimuth & roll
  412.     ax.view_init(elev=10, azim=40, roll=0)
  413.    
  414.     # Sort keywords based on their mean values in descending order (from largest to smallest)
  415.     sorted_keywords = sorted(keywords, key=lambda keyword: interest_over_time[keyword].mean(), reverse=True)
  416.  
  417.     # Generate a color map with a different color for each keyword
  418.     colors = plt.cm.tab10(np.arange(len(keywords)))
  419.  
  420.     # Calculate total frames
  421.     total_frames = min(len(interest_over_time), num_months)
  422.  
  423.     def update(frame):
  424.         # Calculate the month
  425.         month = frame + 1
  426.  
  427.         # Calculate percent_complete based on the current frame and total frames
  428.         percent_complete = (frame + 1) / total_frames * 100
  429.  
  430.         # Calculate the number of elements in each frame
  431.         elements_per_frame = len(interest_over_time) // num_months
  432.  
  433.         # Calculate the start and end indices for the current frame
  434.         start_index = frame * elements_per_frame
  435.         end_index = (frame + 1) * elements_per_frame
  436.  
  437.         # Use iloc to ensure consistent slicing
  438.         ys = interest_over_time.iloc[start_index:end_index][sorted_keywords]
  439.  
  440.         ax.clear()  # Clear the previous frame
  441.  
  442.         for k, keyword in enumerate(sorted_keywords):
  443.             xs = np.arange(len(ys))
  444.             zs = np.full(len(ys), k)  # Use np.full to create an array with the same value (k) for each element
  445.  
  446.             # Create 3D bars using bar3d function with defined width and depth
  447.             ax.bar3d(xs, zs, np.zeros(len(xs)), dx=bar_width, dy=bar_depth, dz=ys[keyword], color=colors[k])
  448.  
  449.         # Display the values of the topics outside the plot
  450.         for k, keyword in enumerate(sorted_keywords):
  451.             value_text = f'{keyword}: {ys[keyword].values[frame] if frame < len(ys[keyword]) else ys[keyword].values[-1]:.1f}'
  452.             ax.text(len(sorted_keywords), k, -10, value_text, fontsize=10, verticalalignment='baseline', color=colors[k])
  453.  
  454.         # Dynamically display the current month number
  455.         current_month = frame + 1
  456.  
  457.         # Set Titles & Labels
  458.         ax.set_title(f'Animated 3D Bar Plot - Month {current_month} / {num_months}\n({percent_complete:.1f}% Complete)', fontsize=14, fontweight='bold')
  459.         ax.set_xlabel('Months', labelpad=20)
  460.         ax.xaxis.label.set_position((-20, 0))
  461.         ax.set_ylabel('Topics', labelpad=20)
  462.         ax.yaxis.label.set_position((-20, 0))
  463.         ax.set_zlabel('Interest Level', labelpad=20)
  464.         ax.zaxis.label.set_position((0, 0))
  465.  
  466.         # Directly set x-axis ticks to match the number of topics
  467.         ax.set_xticks(np.arange(len(sorted_keywords)))
  468.         # Set x-axis ticks to display topics
  469.         ax.set_xticklabels([])
  470.  
  471.         # Set y-axis ticks to match the number of sorted_keywords
  472.         ax.set_yticks(np.arange(len(sorted_keywords)))
  473.         # Set y-axis ticks to display sorted_keywords
  474.         ax.set_yticklabels([])
  475.  
  476.         # Set z-axis ticks from 0 to 100
  477.         ax.set_zticks(np.arange(0, 110, 10))
  478.         # Set z-axis limit 0 to 100
  479.         ax.set_zlim(0, 100)
  480.  
  481.     # Create the animation
  482.     animation_3d_bar = animation.FuncAnimation(fig, update, frames=total_frames, interval=250, repeat=False)
  483.  
  484.     plt.show()
  485.  
  486.  
  487.  
  488. # STATIC 3D BAR PLOT
  489. def generate_3d_bar_plot(interest_over_time, keywords):
  490.     """
  491.    Generate and display a static 3D bar plot.
  492.  
  493.    Parameters:
  494.    - interest_over_time (DataFrame): Dataframe containing interest over time.
  495.    - keywords (List[str]): List of keywords to plot.
  496.    """
  497.  
  498.     print("\nGenerating 3D Bar Plot...")
  499.  
  500.     fig = plt.figure(figsize=(8, 8))
  501.     ax = fig.add_subplot(projection='3d')
  502.  
  503.     # Set figure elevation, azimuth & roll
  504.     ax.view_init(elev=10, azim=40, roll=0)
  505.  
  506.     # Calculate mean values for each keyword
  507.     mean_values = [interest_over_time[keyword].mean() for keyword in keywords]
  508.  
  509.     # Sort keywords and mean values based on mean values in descending order
  510.     sorted_data = sorted(zip(keywords, mean_values), key=lambda x: x[1], reverse=True)
  511.     sorted_keywords, sorted_mean_values = zip(*sorted_data)
  512.  
  513.     # Generate a color map with a different color for each keyword
  514.     colors = plt.cm.tab10(np.arange(len(sorted_keywords)))
  515.  
  516.     max_rows = min(len(sorted_keywords), 5)  # Set a maximum of 5 rows
  517.     max_cells = min(len(interest_over_time), 5)  # Set a maximum of 5 cells (1 row * 5 columns)
  518.  
  519.     for k, keyword in enumerate(sorted_keywords):
  520.         xs = np.arange(max_cells)
  521.         zs = np.full(len(xs), k)  # Use np.full to create an array with the same value (k) for each element
  522.         ys = np.full(len(xs), sorted_mean_values[k])
  523.  
  524.         # Create 3D bars using bar3d function with defined width and depth
  525.         ax.bar3d(xs, zs, np.zeros(len(xs)), dx=1, dy=1, dz=ys, color=colors[k])
  526.  
  527.     # Display the values of the topics outside the plot
  528.     for k, (keyword, mean_value) in enumerate(zip(sorted_keywords, sorted_mean_values)):
  529.         value_text = f'{keyword}: {mean_value:.1f}'
  530.         ax.text(max_cells + 0.5, k - 0.5, -10, value_text, fontsize=10, verticalalignment='baseline', color=colors[k])
  531.  
  532.     # Set Titles & Labels
  533.     ax.set_title('Static 3D Bar Plot', fontsize=14, fontweight='bold')
  534.     ax.set_xlabel('Months', labelpad=20)
  535.     ax.xaxis.label.set_position((-20, 0))
  536.     ax.set_ylabel('Topics')
  537.     ax.set_zlabel('Interest Level', labelpad=20)
  538.     ax.zaxis.label.set_position((0, 0))
  539.  
  540.     # Directly set x-axis ticks to match the number of months
  541.     ax.set_xticks(np.arange(max_cells))
  542.     # Set x-axis ticks to display months
  543.     ax.set_xticklabels([])
  544.  
  545.     # Set y-axis ticks to match the number of sorted_keywords
  546.     ax.set_yticks(np.arange(max_rows))
  547.     # Set y-axis ticks to display sorted_keywords
  548.     ax.set_yticklabels([])
  549.  
  550.     # Set z-axis ticks from 0 to the total value
  551.     ax.set_zticks(np.arange(0, 110, 10))
  552.     # Set z-axis limit 0 to the total value
  553.     ax.set_zlim(0, 100)
  554.  
  555.     plt.show()
  556.    
  557.    
  558.  
  559. # GENERATE BAR PLOT
  560. def generate_bar_plot(interest_over_time, keywords):
  561.     '''
  562.        GENERATE AND DISPLAY A BAR PLOT BASED ON USER'S CHOICE (2D OR 3D).
  563.  
  564.        PARAMETERS:
  565.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  566.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  567.    '''
  568.  
  569.     try:
  570.         # Ask the user if they want 2D or 3D
  571.         bar_type = input("\nChoose the bar plot type: \n1: 2D\n2: 3D\nYour Choice (1 or 2): ")
  572.  
  573.         if bar_type == '1':
  574.             generate_2d_bar_plot(interest_over_time, keywords)
  575.         elif bar_type == '2':
  576.             generate_3d_bar_plot(interest_over_time, keywords)
  577.         else:
  578.             print("Invalid choice. Please enter 1 for 2D or 2 for 3D.")
  579.  
  580.     except ValueError:
  581.         print("\nInvalid input. Please enter a valid number.\n")
  582.        
  583. '''                    [PIE CHARTS]'''
  584.  
  585. # ANIMATED PIE CHART
  586. def animate_pie_chart(interest_over_time, keywords, num_months):
  587.     '''
  588.        GENERATE AND DISPLAY AN ANIMATED PIE CHART WITH AVERAGE VALUES.
  589.  
  590.        PARAMETERS:
  591.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  592.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO INCLUDE IN THE PIE CHART.
  593.        - NUM_MONTHS (INT): NUMBER OF MONTHS FOR WHICH THE AVERAGE VALUES ARE CALCULATED.
  594.    '''
  595.     print("\nAnimating Pie Chart (Average)...")
  596.  
  597.     average_values = interest_over_time[keywords].mean()
  598.  
  599.     # Calculate total frames
  600.     total_frames = len(interest_over_time)
  601.  
  602.     fig, ax = plt.subplots(figsize=(8, 8))
  603.  
  604.     def update(frame):
  605.         ax.clear()
  606.  
  607.         # Calculate the percentage of completion
  608.         percent_complete = (frame + 1) / total_frames * 100
  609.  
  610.         # Calculate the average values for the current frame
  611.         current_frame = frame * len(interest_over_time) // total_frames
  612.         current_values = interest_over_time.iloc[current_frame][keywords]
  613.  
  614.         # Create a pie chart for the current frame
  615.         wedges, texts, autotexts = ax.pie(current_values, labels=[f'{keyword}\nAverage: {current_values[keyword]:.2f}' for keyword in keywords],
  616.                                           autopct='', startangle=140, wedgeprops=dict(width=0.3))
  617.  
  618.         # Calculate the center of the pie chart
  619.         center_x, center_y = np.mean([wedge.center for wedge in wedges], axis=0)
  620.  
  621.         # Adjust the starting offset and offset
  622.         start_offset = -1.80
  623.         offset = -0.20
  624.  
  625.         for i, keyword in enumerate(keywords):
  626.             ax.text(center_x, center_y - (start_offset + i) * offset, f'{keyword}\nAverage: {current_values[keyword]:.2f}', ha='center', va='center', color='black', fontsize=10)
  627.  
  628.         ax.set_title(f'Animated Pie Chart - (Average Strength)\n{percent_complete:.2f}% Complete')
  629.  
  630.     # Create the animation
  631.     animation_pie_chart = animation.FuncAnimation(fig, update, frames=total_frames, interval=250, repeat=False)
  632.  
  633.     plt.show()
  634.  
  635. # GENERATE PIE CHART
  636. def generate_pie_chart(interest_over_time, keywords, num_months):
  637.     '''
  638.        GENERATE AND DISPLAY A STATIC PIE CHART WITH AVERAGE VALUES.
  639.  
  640.        PARAMETERS:
  641.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  642.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO INCLUDE IN THE PIE CHART.
  643.        - NUM_MONTHS (INT): NUMBER OF MONTHS FOR WHICH THE AVERAGE VALUES ARE CALCULATED.
  644.    '''
  645.     print("\nGenerating Pie Chart (Average Strength)...")
  646.  
  647.     average_values = interest_over_time[keywords].mean()
  648.  
  649.     plt.figure(figsize=(8, 8))
  650.     wedges, texts, autotexts = plt.pie(average_values, labels=[f'{keyword}\nAverage: {average_values[keyword]:.2f}' for keyword in keywords],
  651.                                        autopct='', startangle=140, wedgeprops=dict(width=0.3))
  652.  
  653.     # Calculate the center of the pie chart
  654.     center_x, center_y = np.mean([wedge.center for wedge in wedges], axis=0)
  655.  
  656.     # Adjust the starting offset and offset
  657.     start_offset = -1.80
  658.     offset = -0.20
  659.  
  660.     for i, keyword in enumerate(keywords):
  661.         plt.text(center_x, center_y - (start_offset + i) * offset, f'{keyword}\nAverage: {average_values[keyword]:.2f}', ha='center', va='center', color='black', fontsize=10)
  662.  
  663.     plt.title(f'Static Pie Chart (Average)')
  664.     plt.show()
  665.  
  666.  
  667. '''                    [SCATTER PLOTS]'''
  668.  
  669. # ANIMATED SCATTER PLOT
  670. def animate_scatter_plot(interest_over_time, keywords, max_months=240):
  671.     '''
  672.        GENERATE AND DISPLAY AN ANIMATED SCATTER PLOT WITH AVERAGES & SOLID MARKERS.
  673.  
  674.        PARAMETERS:
  675.  
  676.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  677.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  678.        - MAX_MONTHS (INT): MAXIMUM NUMBER OF MONTHS TO ANIMATE (MAX IS 240).
  679.    '''
  680.     print("\nAnimating Scatter Plot...")
  681.  
  682.     fig, ax = plt.subplots(figsize=(16, 8))
  683.     colors = plt.cm.viridis(np.linspace(0, 1, len(keywords)))
  684.  
  685.     def update(frame):
  686.         ax.clear()
  687.  
  688.         # Calculate the month
  689.         month = frame + 1
  690.  
  691.         # Plot the scatter chart for the current month
  692.         start_index = frame * len(interest_over_time) // max_months
  693.         end_index = (frame + 1) * len(interest_over_time) // max_months
  694.         xs = interest_over_time.index[:end_index]
  695.        
  696.         for k, keyword in enumerate(keywords):
  697.             ys = interest_over_time[keyword][:end_index]
  698.  
  699.             # Use different colors for each keyword
  700.             color = colors[k]
  701.  
  702.             # Plot the scatter plot for the current keyword
  703.             scatter = ax.scatter(xs, ys, color=color, label=f'{keyword} - Avg: {ys.mean():.2f}')
  704.  
  705.             # Plot the average line for the current keyword
  706.             avg_interest = ys.mean()
  707.             ax.axhline(y=avg_interest, color=color, linestyle='--', linewidth=1)
  708.  
  709.         # Calculate the percentage of completion
  710.         percent_complete = (month / max_months) * 100
  711.  
  712.         ax.set_title(f'Animated Scatter Plot - (Percent Complete - {percent_complete:.2f}%)')
  713.         ax.set_xlabel('Month')
  714.         ax.set_ylabel('Interest Level')
  715.         ax.legend(loc='upper left')
  716.  
  717.         # Set y-axis ticks from 0 to 100 in increments of 10
  718.         ax.set_yticks(np.arange(0, 110, 10))
  719.  
  720.         # Set the fixed height for the y-axis
  721.         ax.set_ylim(0, 100)
  722.  
  723.     # Calculate total frames
  724.     total_frames = min(len(interest_over_time), max_months)
  725.  
  726.     # Create the animation
  727.     animation_scatter = animation.FuncAnimation(fig, update, frames=total_frames, interval=100, repeat=False)
  728.  
  729.     plt.show()
  730.  
  731.  
  732. # GENERATE SCATTER PLOT
  733. def generate_scatter_plot(interest_over_time, keywords):
  734.     '''
  735.        GENERATE AND DISPLAY A SCATTER PLOT.
  736.  
  737.        PARAMETERS:
  738.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  739.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  740.    '''
  741.     print("\nGenerating Scatter Plot...")
  742.  
  743.     plt.figure(figsize=(16, 8))
  744.  
  745.     # Set a list of distinct colors and markers for each keyword
  746.     colors = plt.cm.viridis(np.linspace(0, 1, len(keywords)))
  747.    
  748.     # Markers Used: 'X': X, '^': Up triangle, '<': Left triangle, '>': Right triangle, 'o': Circle.
  749.     markers = ['X', '^', '<', '>', 'o']  # Set the 5 markers to display
  750.  
  751.        
  752.     # Calculate strengths based on the maximum interest value for each keyword
  753.     strengths = [interest_over_time[keyword].max() for keyword in keywords]
  754.  
  755.     for i, keyword in enumerate(keywords):
  756.         # Use strengths (divided by 0.50) to set the size of the points
  757.         # Use different markers for each keyword
  758.         plt.scatter(interest_over_time.index, interest_over_time[keyword],
  759.                     label=None, s=strengths[i]/0.50, color=colors[i], marker=markers[i])
  760.  
  761.     # Draw the average lines outside the loop
  762.     avg_values = []
  763.     for i, keyword in enumerate(keywords):
  764.         avg_interest = interest_over_time[keyword].mean()
  765.         avg_values.append(avg_interest)
  766.         plt.axhline(y=avg_interest, color=colors[i], linestyle='--', linewidth=1, label=f'{keyword} - Avg: {avg_interest:.2f}')
  767.  
  768.     # Create custom legend with correct markers
  769.     custom_legend = [Line2D([0], [0], marker=markers[i], color=colors[i], label=f'{keywords[i]}') for i in range(len(keywords))]
  770.     plt.legend(handles=custom_legend, loc='upper left')
  771.  
  772.     plt.title('Static Scatter Plot')
  773.     plt.xlabel('Date')
  774.     plt.ylabel('Interest Level')
  775.  
  776.     # Set y-axis ticks from 0 to 100 in increments of 10
  777.     plt.yticks(np.arange(0, 110, 10))
  778.  
  779.     # Set the fixed height for the y-axis
  780.     plt.ylim(0, 100)
  781.  
  782.     plt.show()
  783.  
  784.  
  785.  
  786. '''                    [STACK PLOTS]'''
  787.  
  788. # ANIMATED STACK PLOT
  789. def animate_stack_plot(interest_over_time, keywords):
  790.     '''
  791.        GENERATE AND DISPLAY AN ANIMATED STACK PLOT.
  792.  
  793.        PARAMETERS:
  794.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  795.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  796.    '''
  797.     print("\nAnimating Stack Plot...")
  798.  
  799.     fig, ax = plt.subplots(figsize=(16, 8))
  800.     colors = plt.cm.viridis(np.linspace(0, 1, len(keywords)))
  801.  
  802.     def update(frame):
  803.         ax.clear()
  804.  
  805.         # Calculate the percentage of completion
  806.         percent_complete = (frame + 1) / total_frames * 100
  807.  
  808.         # Extract interest values for each keyword
  809.         y_values = [interest_over_time[keyword].iloc[:frame + 1] for keyword in keywords]
  810.  
  811.         # Create a stack plot for the current frame
  812.         ax.stackplot(interest_over_time.index[:frame + 1], y_values, labels=keywords, colors=colors, alpha=0.7)
  813.  
  814.         ax.set_title(f'Animated Stack Plot - ({percent_complete:.2f}% Complete)')
  815.         ax.set_xlabel('Date')
  816.         ax.set_ylabel('Interest Level')
  817.         ax.legend(loc='upper left')
  818.  
  819.         # Set y-axis ticks from 0 to 300 in increments of 20
  820.         ax.set_yticks(np.arange(0, 320, 20))
  821.         # Set the fixed height for the y-axis
  822.         ax.set_ylim(0, 300)
  823.  
  824.     # Calculate total frames
  825.     total_frames = len(interest_over_time)
  826.  
  827.     # Create the animation
  828.     animation_stack_plot = animation.FuncAnimation(fig, update, frames=total_frames, interval=250, repeat=False)
  829.  
  830.     plt.show()
  831.  
  832. # GENERATE STACK PLOT
  833. def generate_stack_plot(interest_over_time, keywords):
  834.     '''
  835.        GENERATE AND DISPLAY A STATIC STACK PLOT.
  836.  
  837.        PARAMETERS:
  838.        - INTEREST_OVER_TIME (DATAFRAME): DATAFRAME CONTAINING INTEREST OVER TIME.
  839.        - KEYWORDS (LIST[STR]): LIST OF KEYWORDS TO PLOT.
  840.    '''
  841.     print("\nGenerating Stack Plot...")
  842.  
  843.     fig, ax = plt.subplots(figsize=(16, 8))  # Create a new figure and axes
  844.  
  845.     # Extract interest values for each keyword
  846.     y_values = [interest_over_time[keyword] for keyword in keywords]
  847.  
  848.     # Create a stack plot
  849.     ax.stackplot(interest_over_time.index, y_values, labels=keywords, alpha=0.7)
  850.  
  851.     plt.title('Static Stack Plot')
  852.     plt.xlabel('Date')
  853.     plt.ylabel('Interest Level')
  854.     plt.legend(loc='upper left')
  855.  
  856.     # Set y-axis ticks from 0 to 300 in increments of 20
  857.     ax.set_yticks(np.arange(0, 320, 20))
  858.     # Set the fixed height for the y-axis
  859.     ax.set_ylim(0, 300)
  860.  
  861.     plt.show()
  862.  
  863.  
  864.  
  865. '''                    [WORDCLOUD] '''
  866.  
  867. '''
  868.    GENERATE AND DISPLAY A WORD CLOUD WITH RELATED (TOP/RISING) DATA OR USER-INPUT TOPICS.
  869.  
  870.    PARAMETERS:
  871.    - PYTRENDS (TrendReq): AN INSTANCE OF THE pytrends LIBRARY FOR FETCHING DATA.
  872.    - KEYWORDS (LIST[STR]): LIST OF KEYWORDS FOR WHICH RELATED DATA IS FETCHED.
  873.    - NUM_RELATED_TOP (INT): NUMBER OF TOP RELATED QUERIES TO FETCH FOR EACH KEYWORD.
  874.    - NUM_RELATED_RISING (INT): NUMBER OF RISING RELATED QUERIES TO FETCH FOR EACH KEYWORD.
  875.    - RELATED_DATA_DISPLAYED (BOOL): FLAG TO INDICATE WHETHER RELATED DATA SHOULD BE DISPLAYED (DEFAULT: FALSE).
  876. '''
  877.  
  878. # GENERATE WORD CLOUD WITH RELATED (TOP/RISING)
  879. def generate_word_cloud(pytrends, keywords, num_related_top, num_related_rising, related_data_displayed=False):
  880.     try:
  881.         related_queries_data = {'top': [], 'rising': []}
  882.  
  883.         def process_related_data(keyword):
  884.             nonlocal related_queries_data
  885.             try:
  886.                 related_queries_top = pytrends.related_queries()[keyword]['top'].head(num_related_top)
  887.                 if not related_queries_top.empty:
  888.                     related_queries_data['top'].extend(related_queries_top['query'])
  889.             except Exception as e:
  890.                 print(f"Failed to get related top queries for '{keyword}'. Error: {e}")
  891.  
  892.             try:
  893.                 related_queries_rising = pytrends.related_queries()[keyword]['rising'].head(num_related_rising)
  894.                 if not related_queries_rising.empty:
  895.                     related_queries_data['rising'].extend(related_queries_rising['query'])
  896.             except Exception as e:
  897.                 print(f"Failed to get related rising queries for '{keyword}'. Error: {e}")
  898.  
  899.         if not related_data_displayed:
  900.             use_related_data = '1'
  901.             if use_related_data == '1':
  902.                 print("\nGenerating Word Cloud with Related Data...\nThis may take some time to process...")
  903.                 for keyword in keywords:
  904.                     process_related_data(keyword)
  905.                 all_queries = ' '.join(related_queries_data['top'] + related_queries_data['rising'])
  906.             elif use_related_data == '2':
  907.                 print("\nGenerating Word Cloud with User Input Topics...\nThis may take some time to process...")
  908.                 all_queries = ' '.join(keywords)
  909.             else:
  910.                 print("\nInvalid choice. Please enter 1 for Related Data or 2 for User Input Topics.")
  911.                 return
  912.         else:
  913.             all_queries = ' '.join(keywords)
  914.  
  915.         wordcloud = WordCloud(width=800, height=800, background_color='white').generate(all_queries)
  916.  
  917.         plt.figure(figsize=(8, 8))
  918.         plt.imshow(wordcloud, interpolation='bilinear')
  919.         plt.axis('off')
  920.         plt.title('')  # Add a title if you need it here
  921.         plt.show()
  922.  
  923.     except ValueError:
  924.         print("\nInvalid input. Please enter a valid number.\n")
  925.        
  926.  
  927. '''                    [MAIN LOGIC]'''
  928.  
  929. '''
  930.    [MAIN LOGIC]:
  931.    THIS SECTION CONTAINS THE CORE LOGIC FOR EXECUTING THE GOOGLE TRENDS DATA ANALYSIS AND VISUALIZATION TOOL.
  932.    IT ENCOMPASSES THE MAIN PROGRAM FLOW, INCLUDING USER INPUT COLLECTION, DATA FETCHING FROM GOOGLE TRENDS,
  933.    AND THE MAIN MENU-DRIVEN INTERFACE FOR GENERATING VARIOUS PLOTS AND ANALYSES. THE CODE STRUCTURE IS
  934.    ORGANIZED INTO MODULAR FUNCTIONS, OFFERING CLARITY AND MAINTAINABILITY. THE MAIN LOOP ENSURES CONTINUOUS
  935.    INTERACTION WITH THE USER UNTIL THE PROGRAM IS EXITED. ERROR HANDLING IS IMPLEMENTED TO MANAGE INVALID
  936.    INPUTS, ENSURING A SMOOTH USER EXPERIENCE. ADDITIONALLY, A SYSTEM RESET FUNCTION IS DEFINED TO CLEAR DATA
  937.    AND RESTART THE ANALYSIS. OVERALL, THIS SECTION FORMS THE BACKBONE OF THE SCRIPT, ORCHESTRATING THE
  938.    INTERACTION BETWEEN THE USER, DATA, & VISUALIZATION COMPONENTS.
  939. '''
  940.  
  941.  
  942.  
  943. '''                    [MAIN MENU]'''
  944.  
  945. try:
  946.     while True:
  947.         header()  # Call the global header
  948.         # Get user selection
  949.         print("\n\t::[SELECT FROM THE MENU OPTIONS]::\n")
  950.         print("::[SINGLE PLOTS]::\t\t::[DISPLAY]::\n")
  951.         print("1: LINE PLOT\t\t\t6: WORDCLOUD + (TOP/RISING)")
  952.         print("2: 3D BAR PLOT\t\t\t7: ALL PLOTS (2D & 3D)")
  953.         print("3: PIE CHART (AVERAGE)")
  954.         print("4: SCATTER PLOT (AVERAGE)")
  955.         print("5: STACK PLOT")
  956.         print("\n\t\t   ::[SYSTEM]::\n\n\t\t   9: RESET PROGRAM\n\t\t   0: Quit\n")
  957.  
  958.         plot_option = input("\nSelect Your Option or... Press [ENTER] For More Information : ")
  959.  
  960.         try:
  961.             # Check if the user pressed [ENTER]
  962.             if not plot_option:
  963.                 # Import and display the content of about.py
  964.                 import about
  965.                 about.display_about_text()
  966.  
  967.                 input("Press [ENTER] to continue to the main menu.")
  968.                 # Check if the user pressed [ENTER]
  969.                 if not plot_option.strip():
  970.                     # Display a message and continue to the main menu
  971.                     print("\nContinuing To The Menu...\n")
  972.                     continue  # Go back to the main menu after displaying the "About" text
  973.                 # Check if the user input is not empty after removing leading and trailing whitespace
  974.                 if plot_option.strip():
  975.                     try:  # Attempt to convert the user input to an integer
  976.                         plot_option = int(plot_option)
  977.                     except ValueError:
  978.                         # If conversion to an integer fails (due to a non-numeric input), do nothing (pass)
  979.                         pass
  980.             # Attempt to convert the user input (plot_option) to an integer
  981.             plot_option = int(plot_option)
  982.  
  983.             '''                    [PLOT OPTIONS]'''
  984.  
  985.             if 0 <= plot_option <= 9:
  986.                 if plot_option == 0:
  987.                     print("\nProgram Exiting...\tGoodBye!\n")
  988.                     break  # Exit the loop and end the script
  989.                 elif plot_option == 1:
  990.                     try:
  991.                         # Ask the user if they want static or animated plots
  992.                         plot_type = input("\nChoose the plot type: \n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  993.  
  994.                         if plot_type == '1':
  995.                             generate_line_plot(interest_over_time, keywords, num_months)
  996.                         elif plot_type == '2':
  997.                             animate_line_plot(interest_over_time, keywords, num_months)
  998.                         else:
  999.                             print("Invalid choice. Please enter 1 for static or 2 for animated.")
  1000.  
  1001.                     except ValueError:
  1002.                         print("\nInvalid input. Please enter a valid number.\n")
  1003.                 elif plot_option == 2:
  1004.                     try:
  1005.                         # Ask the user if they want static or animated plots
  1006.                         plot_type = input("\nChoose the plot type: \n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  1007.  
  1008.                         if plot_type == '1':
  1009.                             # Ask the user for 2D or 3D static plot
  1010.                             static_plot_type = input("\nChoose the static plot type: \n1: 2D\n2: 3D\nYour Choice (1 or 2): ")
  1011.  
  1012.                             if static_plot_type == '1':
  1013.                                 generate_2d_bar_plot(interest_over_time, keywords)
  1014.                             elif static_plot_type == '2':
  1015.                                 generate_3d_bar_plot(interest_over_time, keywords)
  1016.                             else:
  1017.                                 print("Invalid choice. Please enter 1 for 2D or 2 for 3D.")
  1018.                         elif plot_type == '2':
  1019.                             # Ask the user for 2D or 3D animated plot
  1020.                             animated_plot_type = input("\nChoose the animated plot type: \n1: 2D\n2: 3D\nYour Choice (1 or 2): ")
  1021.  
  1022.                             if animated_plot_type == '1':
  1023.                                 animate_2d_bar_plot(interest_over_time, keywords)
  1024.                             elif animated_plot_type == '2':
  1025.                                 animate_3d_bar_plot(interest_over_time, keywords)
  1026.                             else:
  1027.                                 print("Invalid choice. Please enter 1 for 2D or 2 for 3D.")
  1028.                         else:
  1029.                             print("Invalid choice. Please enter 1 for static or 2 for animated.")
  1030.                     except ValueError:
  1031.                         print("\nInvalid input. Please enter a valid number.\n")
  1032.                 elif plot_option == 3:
  1033.                     try:
  1034.                         # Ask the user if they want static or animated pie chart
  1035.                         plot_type = input("\nChoose the pie chart type: \n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  1036.  
  1037.                         if plot_type == '1':
  1038.                             generate_pie_chart(interest_over_time, keywords, num_months)
  1039.                         elif plot_type == '2':
  1040.                             animate_pie_chart(interest_over_time, keywords, num_months)
  1041.                         else:
  1042.                             print("Invalid choice. Please enter 1 for static or 2 for animated.")
  1043.  
  1044.                     except ValueError:
  1045.                         print("\nInvalid input. Please enter a valid number.\n")
  1046.                 elif plot_option == 4:
  1047.                     try:
  1048.                         # Ask the user if they want static or animated plots
  1049.                         plot_type = input("\nChoose the plot type: \n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  1050.  
  1051.                         if plot_type == '1':
  1052.                             generate_scatter_plot(interest_over_time, keywords)
  1053.                         elif plot_type == '2':
  1054.                             animate_scatter_plot(interest_over_time, keywords)
  1055.                         else:
  1056.                             print("Invalid choice. Please enter 1 for static or 2 for animated.")
  1057.  
  1058.                     except ValueError:
  1059.                         print("\nInvalid input. Please enter a valid number.\n")                        
  1060.                 elif plot_option == 5:
  1061.                     try:
  1062.                         # Ask the user if they want static or animated plots
  1063.                         plot_type = input("\nChoose the plot type: \n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  1064.  
  1065.                         if plot_type == '1':
  1066.                             generate_stack_plot(interest_over_time, keywords)
  1067.                         elif plot_type == '2':
  1068.                             animate_stack_plot(interest_over_time, keywords)
  1069.                         else:
  1070.                             print("Invalid choice. Please enter 1 for static or 2 for animated.")
  1071.  
  1072.                     except ValueError:
  1073.                         print("\nInvalid input. Please enter a valid number.\n")
  1074.                 elif plot_option == 6:
  1075.                     try:
  1076.                         num_related_top = int(input("\nEnter the number of related top queries to include in the word cloud (Max 24):\n"))
  1077.                         num_related_rising = int(input("\nEnter the number of related rising queries to include in the word cloud (Max 24):\n"))
  1078.  
  1079.                         # Call the generate_word_cloud function and get the words
  1080.                         wordcloud_words = generate_word_cloud(pytrends, keywords, num_related_top, num_related_rising)
  1081.                        
  1082.                     except ValueError:
  1083.                         print("\nInvalid input. Please enter a valid number.\n")
  1084.                 elif plot_option == 7:
  1085.                     # Ask the user if they want static or animated plots
  1086.                     plot_type = input("\nChoose plot type:\n1: Static\n2: Animated\nYour Choice (1 or 2): ")
  1087.  
  1088.                     if plot_type == '1':
  1089.                         # Ask the user for 2D or 3D static plot
  1090.                         static_plot_type = input("\nChoose the static plot type: \n1: 2D\n2: 3D\nYour Choice (1 or 2): ")
  1091.  
  1092.                         if static_plot_type == '1':
  1093.                             generate_line_plot(interest_over_time, keywords, num_months)
  1094.                             generate_scatter_plot(interest_over_time, keywords)
  1095.                             generate_stack_plot(interest_over_time, keywords)
  1096.                             generate_2d_bar_plot(interest_over_time, keywords)
  1097.                             generate_pie_chart(interest_over_time, keywords, num_months)
  1098.  
  1099.                         elif static_plot_type == '2':
  1100.                             generate_line_plot(interest_over_time, keywords, num_months)
  1101.                             generate_scatter_plot(interest_over_time, keywords)
  1102.                             generate_stack_plot(interest_over_time, keywords)
  1103.                             generate_3d_bar_plot(interest_over_time, keywords)
  1104.                             generate_pie_chart(interest_over_time, keywords, num_months)
  1105.  
  1106.                         else:
  1107.                             print("Invalid choice for static plot type. Please enter 1 for 2D or 2 for 3D.")
  1108.  
  1109.                     elif plot_type == '2':
  1110.                         # Ask the user for 2D or 3D animated plot
  1111.                         animated_plot_type = input("\nChoose the animated plot type: \n1: 2D\n2: 3D\nYour Choice (1 or 2): ")
  1112.  
  1113.                         if animated_plot_type == '1':
  1114.                             animate_line_plot(interest_over_time, keywords, num_months)
  1115.                             animate_scatter_plot(interest_over_time, keywords)
  1116.                             animate_stack_plot(interest_over_time, keywords)
  1117.                             animate_2d_bar_plot(interest_over_time, keywords)
  1118.                             animate_pie_chart(interest_over_time, keywords, num_months)
  1119.  
  1120.                         elif animated_plot_type == '2':
  1121.                             animate_line_plot(interest_over_time, keywords, num_months)
  1122.                             animate_scatter_plot(interest_over_time, keywords)
  1123.                             animate_stack_plot(interest_over_time, keywords)
  1124.                             animate_3d_bar_plot(interest_over_time, keywords)
  1125.                             animate_pie_chart(interest_over_time, keywords, num_months)
  1126.  
  1127.                         else:
  1128.                             print("Invalid choice for animated plot type. Please enter 1 for 2D or 2 for 3D.")
  1129.  
  1130.                     if related_data_displayed:
  1131.                         wordcloud = generate_word_cloud(pytrends, keywords, num_related_top, num_related_rising, related_data_displayed)
  1132.                         if wordcloud:
  1133.                             # Display the word cloud using matplotlib
  1134.                             plt.figure(figsize=(8, 8))
  1135.                             plt.imshow(wordcloud, interpolation='bilinear')
  1136.                             plt.axis('off')
  1137.                             plt.title('Word Cloud of Related Queries')
  1138.                             plt.show()
  1139.                 elif plot_option == 9:
  1140.                     # Reset the program and clear data
  1141.                     reset_program()
  1142.  
  1143.                     # Continue directly to the main menu
  1144.                     continue
  1145.  
  1146.             else:
  1147.                 # Handling Invalid Options
  1148.                 print("\nInvalid option. Please enter a valid number between 0 and 7.\n")
  1149.                 # Exception Handling for Non-Integer Option
  1150.         except ValueError:
  1151.             print("\nInvalid input. Please enter a valid number.\n")
  1152.  
  1153.         else:
  1154.             # Exception Handling for Invalid Number of Months
  1155.             print("\nInvalid number of months. Please enter a number between 1 and 240.\n")
  1156. except ValueError:
  1157.     print("\nInvalid input. Please enter a valid number.\n")
  1158.  
  1159.  
  1160.  
  1161.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement