from imports import * # Création des dossiers nécessaires os.makedirs("request", exist_ok=True) os.makedirs("saved_dataframes", exist_ok=True) # Initialisation des listes dynamiques avec mise à jour dynamique des fichiers dataframes = {} # Stocke les DataFrames chargés saved_dataframe_files = [ f.strip() for f in os.listdir("saved_dataframes") if f.endswith(".csv") ] saved_request_files = [ f.strip() for f in os.listdir("request") if f.endswith(".txt") ] def update_saved_files(): """Met à jour les listes de fichiers enregistrés.""" global saved_dataframe_files, saved_request_files saved_dataframe_files = [ f.strip() for f in os.listdir("saved_dataframes") if f.endswith(".csv") ] saved_request_files = [ f.strip() for f in os.listdir("request") if f.endswith(".txt") ] def open_access_file(): """Ouvre une boîte de dialogue pour sélectionner un fichier Access, toujours en avant-plan.""" mGui = Tk() mGui.withdraw() # Cache la fenêtre principale mGui.attributes("-topmost", True) # Toujours au premier plan print("Veuillez sélectionner un fichier Access...") file_path = filedialog.askopenfilename( title="Choisissez un fichier Access", filetypes=[("Fichiers Access", "*.mdb;*.accdb"), ("Tous les fichiers", "*.*")] ) mGui.destroy() # Détruit la fenêtre principale après usage return file_path def load_access_databases(): """Gère l'import de plusieurs bases de données Access et la création de DataFrames.""" global dataframes while True: add_file = input("Voulez-vous ajouter un fichier Access ? (o/n) : ").lower() if add_file != 'o': break file_path = open_access_file() if not file_path: print("Aucun fichier sélectionné.") continue print(f"Fichier Access sélectionné : {file_path}") query = input("Entrez une requête SQL pour cette base (ou tapez 'retour' pour annuler) : ") if query.lower() == "retour": continue while True: df_name = input("Donnez un nom unique au DataFrame (ou tapez 'retour' pour annuler) : ") if df_name.lower() == "retour": break df_path = f"saved_dataframes/{df_name}.csv" query_path = f"request/{df_name}.txt" if os.path.exists(df_path) or os.path.exists(query_path): print("Erreur : Ce nom existe déjà. Veuillez en choisir un autre.") else: break with open(query_path, 'w') as f: f.write(query) print(f"Requête SQL enregistrée dans {query_path}.") try: conn_str = f"Driver={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={file_path};" conn = pyodbc.connect(conn_str) df = pd.read_sql_query(query, conn) conn.close() # Suppression des doublons df = df.drop_duplicates() df.to_csv(df_path, index=False) print(f"DataFrame enregistré dans {df_path}. Les doublons ont été supprimés.") update_saved_files() # Mettre à jour les fichiers enregistrés except Exception as e: print(f"Erreur lors de l'exécution de la requête : {e}") def view_saved_dataframes(): """Affiche la liste des noms des DataFrames enregistrés et les détails si demandé.""" update_saved_files() if not saved_dataframe_files: print("Aucun DataFrame enregistré.") return print("DataFrames enregistrés :") for idx, file in enumerate(saved_dataframe_files, 1): print(f"{idx}. {file}") print("0. Retour") while True: try: choice = int(input("Entrez le numéro du DataFrame pour voir ses détails (ou 0 pour revenir) : ")) if choice == 0: return elif 1 <= choice <= len(saved_dataframe_files): file_name = saved_dataframe_files[choice - 1] df_path = os.path.join("saved_dataframes", file_name) if file_name not in dataframes: dataframes[file_name] = pd.read_csv(df_path) # Charger le DataFrame si ce n'est pas déjà fait print(f"\nDétails du DataFrame '{file_name}':") print(dataframes[file_name].head()) # Afficher l'entête et les 5 premières lignes else: print("Numéro invalide.") except ValueError: print("Veuillez entrer un numéro valide.") def create_new_sql_query(): """Permet à l'utilisateur de sélectionner un ou plusieurs DataFrames pour une nouvelle requête SQL.""" global dataframes selected_dfs = {} update_saved_files() if not saved_dataframe_files: print("Aucun DataFrame disponible pour une requête. Veuillez d'abord charger des DataFrames.") return # Sélectionner les DataFrames nécessaires while True: print("\nDataFrames disponibles :") for idx, file in enumerate(saved_dataframe_files, 1): print(f"{idx}. {file}") print("0. Retour") try: choice = int(input("Entrez le numéro du DataFrame à sélectionner (ou 0 pour revenir) : ")) if choice == 0: return elif 1 <= choice <= len(saved_dataframe_files): file_name = saved_dataframe_files[choice - 1] df_path = os.path.join("saved_dataframes", file_name) if file_name not in dataframes: dataframes[file_name] = pd.read_csv(df_path) table_name = file_name.split(".")[0] selected_dfs[table_name] = dataframes[file_name] print(f"DataFrame '{file_name}' sélectionné comme table '{table_name}'.") print(dataframes[file_name].head()) # Afficher les 5 premières lignes # Demander si l'utilisateur veut ajouter un autre DataFrame add_more = input("Voulez-vous ajouter un autre DataFrame ? (o/n) : ").lower() if add_more != 'o': break else: print("Numéro invalide.") except ValueError: print("Veuillez entrer un numéro valide.") if not selected_dfs: print("Aucune table sélectionnée pour la requête.") return # Demander la requête SQL query = input("Entrez une requête SQL pour créer un nouveau DataFrame (ou tapez 'retour' pour annuler) : ") if query.lower() == "retour": return while True: new_df_name = input("Donnez un nom unique au nouveau DataFrame (ou tapez 'retour' pour annuler) : ") if new_df_name.lower() == "retour": return df_path = f"saved_dataframes/{new_df_name}.csv" query_path = f"request/{new_df_name}.txt" if os.path.exists(df_path) or os.path.exists(query_path): print("Erreur : Ce nom existe déjà. Veuillez en choisir un autre.") else: break # Sauvegarder la requête SQL with open(query_path, 'w') as f: f.write(query) print(f"Requête SQL enregistrée dans {query_path}.") try: conn_str = "sqlite:///:memory:" engine = create_engine(conn_str) # Charger chaque DataFrame dans SQLite avec son nom for table_name, df in selected_dfs.items(): sanitized_table_name = f'"{table_name}"' df.to_sql(sanitized_table_name, engine, index=False, if_exists='replace') print(f"Table '{table_name}' ajoutée à la base SQLite temporaire.") # Exécuter la requête SQL sur la base temporaire new_df = pd.read_sql_query(query, engine) # Suppression des doublons new_df = new_df.drop_duplicates() # Sauvegarder le nouveau DataFrame new_df.to_csv(df_path, index=False) update_saved_files() # Mettre à jour les fichiers enregistrés print(f"Le nouveau DataFrame '{new_df_name}' a été créé et enregistré dans {df_path}. Les doublons ont été supprimés.") except Exception as e: print(f"Erreur lors de l'exécution de la requête : {e}") def generate_graph(): """Générer un graphique interactif en Matplotlib avec une échelle simulée.""" global dataframes, saved_dataframe_files if not saved_dataframe_files: print("Aucun DataFrame disponible pour générer un graphique. Veuillez d'abord charger des DataFrames.") return # Sélectionner un DataFrame while True: print("\nDataFrames disponibles :") for idx, file in enumerate(saved_dataframe_files, 1): print(f"{idx}. {file}") print("0. Retour") try: choice = int(input("Entrez le numéro du DataFrame à utiliser pour le graphique (ou 0 pour revenir) : ")) if choice == 0: return elif 1 <= choice <= len(saved_dataframe_files): file_name = saved_dataframe_files[choice - 1] df_path = os.path.join("saved_dataframes", file_name) if file_name not in dataframes: dataframes[file_name] = pd.read_csv(df_path) selected_df = dataframes[file_name] print(f"DataFrame '{file_name}' sélectionné.") print("Voici les 5 premières lignes du DataFrame sélectionné :") print(selected_df.head()) break else: print("Numéro invalide.") except ValueError: print("Veuillez entrer un numéro valide.") # Demander les colonnes pour freq_min, freq_max et sat_name print("\nColonnes disponibles dans le DataFrame :") print(list(selected_df.columns)) while True: freq_min_col = input("Entrez le nom de la colonne pour la fréquence minimale (freq min) : ") freq_max_col = input("Entrez le nom de la colonne pour la fréquence maximale (freq max) : ") sat_col = input("Entrez le nom de la colonne pour le nom des satellites (sat_name) : ") color_col = input("Entrez le nom de la colonne pour la couleur (ex. op_agcy_name) : ") if all(col in selected_df.columns for col in [freq_min_col, freq_max_col, sat_col, color_col]): break else: print("Une ou plusieurs colonnes saisies sont invalides. Veuillez réessayer.") # Préparer les données selected_df[freq_min_col] = pd.to_numeric(selected_df[freq_min_col], errors='coerce') selected_df[freq_max_col] = pd.to_numeric(selected_df[freq_max_col], errors='coerce') # Filtrer les bandes valides selected_df = selected_df[(selected_df[freq_min_col] > 0) & (selected_df[freq_max_col] > 0)] selected_df = selected_df[selected_df[freq_min_col] < selected_df[freq_max_col]] if selected_df.empty: print("Erreur : Aucun intervalle valide trouvé après le filtrage des données.") return # Création du graphique fig, ax = plt.subplots(figsize=(12, 8)) plt.subplots_adjust(bottom=0.2) for _, row in selected_df.iterrows(): ax.plot( [row[freq_min_col], row[freq_max_col]], [row[sat_col], row[sat_col]], color=plt.cm.tab20(hash(row[color_col]) % 20 / 20), linewidth=5 ) ax.set_xlabel("Fréquence (MHz)") ax.set_ylabel("Satellites") ax.set_title("Bandes de fréquence par satellite") ax.grid(True) plt.show() def main_menu(): """Affiche le menu principal et gère les actions de l'utilisateur.""" while True: print("\nMenu principal :") print("1. Charger une ou plusieurs bases de données Access") print("2. Voir les DataFrames enregistrés") print("3. Nouvelle requête SQL") print("4. Générer graphique") print("5. Quitter le programme") choice = input("Entrez votre choix : ") if choice == '1': load_access_databases() elif choice == '2': view_saved_dataframes() elif choice == '3': create_new_sql_query() elif choice == '4': generate_graph() elif choice == '5': print("Fermeture du programme.") break else: print("Choix invalide. Veuillez réessayer.") if __name__ == "__main__": main_menu()