Browse Source

interface fonctionnelle ; correction d'erreurs dans knn

master
bollet.c 6 months ago
parent
commit
0081543cfb
  1. 66
      ihm.py
  2. 8
      knn.py
  3. 12
      lecture.py
  4. 148
      selection.py
  5. 11
      test.py

66
ihm.py

@ -1,46 +1,76 @@
import tkinter as tk
from test import lancerTest
from tkinter import ttk
from selection import DateSelection, TemperatureSelection, VoisinSelection
class Interface(tk.Frame):
def __init__(self, master):
"""initialisation de l'interface"""
self.master = master
tk.Frame.__init__(self, master)
self.create_menu_bar()
self.tabs = ttk.Notebook(self.master)
self.create_tabs()
nb_voisins_proches = tk.Entry(self.master)
nb_voisins_proches.pack(fill="both")
btn_entrer = tk.Button(frame_saisie, text='entrer')
btn_entrer.pack()
def create_menu_bar(self):
"""crée la barre de menu"""
menu_bar = tk.Menu(self)
menu_file = tk.Menu(menu_bar, tearoff=0)
menu_file.add_command(label="Quitter", command=self.master.destroy)
menu_bar.add_cascade(label="Fichier", menu=menu_file)
menu_affichage = tk.Menu(menu_bar, tearoff=0)
self.master['menu']=menu_bar
menu_mode = tk.Menu(menu_bar, tearoff=0)
menu_affichage.add_command(label="préfixe (polonaise)")
menu_affichage.add_command(label="infixe")
def create_tabs(self):
"""crée les onglets et les widgets à l'intérieur"""
menu_mode.add_command(label="mode interactif")
menu_mode.add_command(label="mode expression")
menu_affichage.add_cascade(label="postfixe (polonaise inversée)", menu=menu_mode)
menu_bar.add_cascade(label="Notation", menu=menu_affichage)
tabAccueil = tk.Frame(self.tabs)
tabTest = tk.Frame(self.tabs)
tabRes = tk.Frame(self.tabs)
self.tabs.add(tabAccueil, text="Accueil")
self.tabs.add(tabTest, text="Données")
self.tabs.add(tabRes, text="Résultats")
self.tabs.pack(expand=1, fill='both')
#accueil
tk.Label(tabAccueil, text="Vizion", font=("Magneto", 70)).pack()
tk.Label(tabAccueil, text="Aɴᴀʟʏsᴇs - Pʀᴇᴅɪᴄᴛɪᴏɴs", font=("arial", 10)).pack()
menu_help = tk.Menu(menu_bar, tearoff=0)
menu_help.add_command(label="Aide")
menu_help.add_command(label="À propos")
menu_bar.add_cascade(label="Aide", menu=menu_help)
tk.Button(tabAccueil, text='Commencer un nouveau test', padx=10, pady=10, command=lambda :self.tabs.select(tabTest)).pack(pady=50)
#test
self.nb_voisins_proches = VoisinSelection(tabTest)
self.master['menu']=menu_bar
param = tk.LabelFrame(tabTest, text="Paramètres", padx=20, pady=20)
param.pack()
self.choix_date = DateSelection(param)
self.choix_temp_moy = TemperatureSelection(param, "Température moyenne")
self.choix_temp_ref = TemperatureSelection(param, "Température de référence")
btn_entrer = tk.Button(tabTest, text='Tester', command=lambda : self.affResTest(tabRes))
btn_entrer.pack()
#res
tk.Label(tabRes, text="Résultat", font=(42)).pack()
self.affichage_resultats = tk.Label(tabRes, text="", font=("Courier", 15))
self.affichage_resultats.pack()
def affResTest(self, tab):
"""affiche le résultat du test dans le label
self.affichage_resultats dans l'onglet TabRes"""
k = self.nb_voisins_proches.get()
date_choisie = self.choix_date.get()
temperature_moyenne = self.choix_temp_moy.get()
temperature_ref = self.choix_temp_ref.get()
res = str(lancerTest(k, (date_choisie, temperature_moyenne, temperature_ref)))
self.affichage_resultats['text'] = "La consommation électrique \nprévue est de " + res + " MW."
self.tabs.select(tab)
if __name__ == "__main__":
root = tk.Tk()

8
knn.py

@ -12,6 +12,7 @@ def distance(point1, point2):
(Date du jour, Température moyenne, température de référence)
et qui renvoie un nombre réel représentant
la distance euclidienne au carré entre ces deux points"""
duree = ecartDate(point1[0], point2[0])
delta_T_moy = (point1[1]-point2[1])**2
delta_T_ref = (point1[2]-point2[2])**2
@ -25,8 +26,9 @@ def kPlusProches(point_a_verifier, tableau, k):
et un tableau au format (Numéro du jour, Température moyenne, Température de référence).
Renvoie un tableau trié avec les k plus proches
points de `point_a_verifier`, au format (distance, indice du tableau original)"""
dist = []
for i, point in enumerate(tableau):
dist.append(distance(point_a_verifier, point), i)
sorted(dist, key=lambda t: t[0])
return dist[:k+1]
dist.append((distance(point_a_verifier, point[0]), i))
dist = sorted(dist, key=lambda t: t[0])
return dist[:k]

12
lecture.py

@ -3,10 +3,18 @@ import csv
def lecture(fichier):
"""renvoie tableau pour
traitement par d'autres programmes"""
tableau = []
with open(fichier, newline='') as csvfile:
lecteur = csv.reader(csvfile)
next(lecteur)
for ligne in lecteur:
tableau.append([(ligne[0], ligne[2], ligne[3]), ligne[1]])
return tableau[1:]
date = ligne[0]
pic_journalier_consommation = float(ligne[1])
temperature_moyenne = float(ligne[2])
temperature_reference = float(ligne[3])
tableau.append([(date, temperature_moyenne, temperature_reference), \
pic_journalier_consommation])
return tableau

148
selection.py

@ -0,0 +1,148 @@
import tkinter as tk
from datetime import date
from tkinter import messagebox
class DateSelection:
def __init__(self, master):
"""initialise le widget"""
self.master = master
self.value = "0001-01-01"
frame_btn_date = tk.LabelFrame(self.master, text="Date", font=(25), fg="gray")
frame_btn_date.pack()
self.button = tk.Button(frame_btn_date, text="Choisir une date", command=self.select)
self.button.pack(padx=10, pady=2, side="left")
self.aff_date = tk.Label(frame_btn_date, text=self.value, padx=10, pady=2, font=(25), fg="gray")
self.aff_date.pack(padx=10, pady=2, side="left")
def select(self):
"""permet de choisir une date au format isoformat"""
self.popup = tk.Toplevel(padx=15, pady=15)
self.popup.wm_title("Veuillez choisir une date")
frame_choix = tk.LabelFrame(self.popup, text="jour / mois / année", font=(50), fg="gray")
frame_choix.pack()
self.jour = tk.Spinbox(frame_choix, from_=1, to=31, font=(100), width=2)
self.jour.pack(side="left", padx=10, pady=10)
tk.Label(frame_choix, text="/", font=(100)).pack(side="left")
self.mois = tk.Spinbox(frame_choix, from_=1, to=12, font=(100), width=2)
self.mois.pack(side="left", padx=10, pady=10)
tk.Label(frame_choix, text="/", font=(100)).pack(side="left")
self.annee = tk.Spinbox(frame_choix, from_=1, to=9999, font=(100), width=4)
self.annee.pack(side="left", padx=10, pady=10)
ok_btn = tk.Button(self.popup, text="OK", command=self.update)
ok_btn.pack()
def update(self):
"""assigne la date choisie (si elle est valide) à self.valeur,
sinon, ne change rien"""
val = self.format2iso()
if self.est_valide(val):
self.value = val
self.aff_date['text'] = self.value
self.popup.destroy()
else:
messagebox.showerror("Erreur", "La date n'est pas valide")
def format2iso(self):
"""renvoie une chaine de caractère avec
la date au format iso"""
aaaa = "0"*(4-len(self.annee.get())) + self.annee.get()
mm = "0"*(2-len(self.mois.get())) + self.mois.get()
jj = "0"*(2-len(self.jour.get())) + self.jour.get()
res = aaaa + "-" + mm + "-" + jj
return res
def est_valide(self, d):
"""renvoie True si la date d est valide,
False sinon"""
try:
date.fromisoformat(d)
return True
except ValueError:
return False
def get(self):
"""renvoie la date choisie"""
return self.value
class TemperatureSelection:
def __init__(self, master, nom):
"""initialise le widget"""
self.master = master
self.value = 0
frame_choix = tk.LabelFrame(self.master, text=nom, font=(25), fg="gray")
frame_choix.pack()
self.choix_tmp = tk.Entry(frame_choix, fg="black")
self.choix_tmp.insert("end", self.value)
self.choix_tmp.pack(side="left", padx=(10,5), pady=10)
self.choix_tmp.bind("<KeyRelease>", lambda e : self.isCorrect())
tk.Label(frame_choix, text="°C", font=(50), fg="gray").pack(side="left")
def isCorrect(self):
"""vérifie que la température entrée est correcte"""
val = self.choix_tmp.get()
if is_float(val) and float(val) > -273.15:
self.choix_tmp['bg'] = 'lightgreen'
self.choix_tmp['fg'] = 'black'
return True
else:
self.choix_tmp['bg'] = 'red'
self.choix_tmp['fg'] = 'white'
return False
def get(self):
"""renvoie la température choisie"""
if self.isCorrect():
return float(self.choix_tmp.get())
else:
return 0 #valeur par défaut
class VoisinSelection:
def __init__(self, master):
"""initialise le widget"""
self.master = master
frame_choix = tk.LabelFrame(self.master, text="Nombre de voisins (k)", font=(25), fg="gray")
frame_choix.pack()
self.choix_k = tk.Entry(frame_choix, font=(100), width=3)
self.choix_k.insert("end", "1")
self.choix_k.pack(pady=10)
def get(self):
"""renvoie le nombre de voisins"""
c = self.choix_k.get()
return int(c) if c.isdigit() and int(c) != 0 else 1
#fonction axiliaire
def is_float(element):
if element is None:
return False
try:
float(element)
return True
except ValueError:
return False

11
test.py

@ -3,9 +3,16 @@ from lecture import lecture
def lancerTest(nombre_voisins, point_a_verifier):
"""effectue prédiction"""
fichier_apprentissage = lecture("data/pic-journalier-consommation.csv")
k_plus_proches = kPlusProches(point_a_verifier, \
fichier_apprentissage, \
nombre_voisins)
conso_prevue = sum(k_plus_proches) / len(k_plus_proches)
return conso_prevue
conso_prevue = 0
liste_indices = [elem[1] for elem in k_plus_proches]
for indice in liste_indices:
pic_conso = fichier_apprentissage[indice][1]
conso_prevue += pic_conso
return conso_prevue / len(k_plus_proches)

Loading…
Cancel
Save