bon, le code est 'bon', j'ai plus qu'à l'épurer et à mettre un peu d'aide au début, là les flèches ne dépasseront jamais un certain seuil, d'ailleurs c'est plus des flèches

This commit is contained in:
DylanVsn 2020-01-29 22:55:11 +01:00
parent 7c3a300947
commit 2e3a2f89ad

View File

@ -5,6 +5,7 @@ from random import random, choice
import numpy as np import numpy as np
from time import sleep from time import sleep
import argparse import argparse
from math import * # pour utliser les fonctions mathématiques dans l'option -f
""" """
MNI TP3 - 27 janvier 2020 MNI TP3 - 27 janvier 2020
@ -68,31 +69,85 @@ def diagonaliser_matrice22(m):
u1 = np.array([u2[1], -u2[0]]) u1 = np.array([u2[1], -u2[0]])
return u1, u2, lambda1, lambda2 return u1, u2, lambda1, lambda2
def get_u1_u2_affichage(u1, u2, bary, dist_x, dist_y, pb, pg):
"""renvoie u1 et u2 prêt pour l'affichage en fonction du barycentre,
de la distance x et y sur l'ensemble des points, le point le plus bas et
le point le plus à gauche"""
if np.linalg.norm(u1) == np.linalg.norm(u2) == 0:
# un seul point
u1 = np.array([1, 0]) / 500
u2 = np.array([0, 1]) / 500
return u1, u2
bary = np.array((bary[0] - pg[0], bary[1] - pb[1]))
if u1[0] != 0 and u1[1] != 0:
if u1[0] > 0: # vers la droite
t1x = (dist_x - bary[0]) / u1[0]
else:
t1x = -bary[0] / u1[0]
if u1[1] > 0: # vers le haut
t1y = (dist_y - bary[1]) / u1[1]
else:
t1y = -bary[1] / u1[1]
t1 = min(t1x, t1y)
elif u1[0] != 0:
if u1[0] > 0: # vers la droite
t1 = (dist_x - bary[0]) / u1[0]
else:
t1 = -bary[0] / u1[0]
else:
if u1[1] > 0: # vers le haut
t1 = (dist_y - bary[1]) / u1[1]
else:
t1 = -bary[1] / u1[1]
if u2[0] != 0 and u2[1] != 0:
if u2[0] > 0: # vers la droite
t2x = (dist_x - bary[0]) / u2[0]
else:
t2x = -bary[0] / u2[0]
if u2[1] > 0: # vers le haut
t2y = (dist_y - bary[1]) / u2[1]
else:
t2y = -bary[1] / u2[1]
t2 = min(t2x, t2y)
elif u2[0] != 0:
if u2[0] > 0: # vers la droite
t2 = (dist_x - bary[0]) / u2[0]
else:
t2 = -bary[0] / u2[0]
else:
if u2[1] > 0: # vers le haut
t2 = (dist_y - bary[1]) / u2[1]
else:
t2 = -bary[1] / u2[1]
u1 = u1 * t1 * 2/3
u2 = u2 * t2 * 1/3
return u1, u2
def get_info_affichage(l_pts): def get_info_affichage(l_pts):
"""renvoie les vecteurs u1 et u2 pour l'affichage ainsi que xmin, xmax, ymin, ymax""" """renvoie les vecteurs u1 et u2 pour l'affichage ainsi que xmin, xmax, ymin, ymax"""
bary = calc_barycentre(l_pts) bary = calc_barycentre(l_pts)
u1, u2 = diagonaliser_matrice22(calc_matrice_corrélation(l_pts))[:2] u1, u2 = diagonaliser_matrice22(calc_matrice_corrélation(l_pts))[:2]
pb = min(l_pts, key = lambda x: x[1])
pg = min(l_pts, key = lambda x: x[0])
dist = min(max(l_pts[:,0]) - bary[0], max(l_pts[:,1]) - bary[1]) dist = min(max(l_pts[:,0]) - bary[0], max(l_pts[:,1]) - bary[1])
# dist = max(map(lambda x: np.linalg.norm(x-bary), l_pts))
dist_x = max(l_pts[:,0]) - min(l_pts[:,0]) dist_x = max(l_pts[:,0]) - min(l_pts[:,0])
dist_y = max(l_pts[:,1]) - min(l_pts[:,1]) dist_y = max(l_pts[:,1]) - min(l_pts[:,1])
x_range = min(l_pts[:,0]) - 0.1 * dist_x, max(l_pts[:,0]) + 0.1 * dist_x x_range = min(l_pts[:,0]) - 0.1 * dist_x, max(l_pts[:,0]) + 0.1 * dist_x
y_range = min(l_pts[:,1]) - 0.1 * dist_y, max(l_pts[:,1]) + 0.1 * dist_y y_range = min(l_pts[:,1]) - 0.1 * dist_y, max(l_pts[:,1]) + 0.1 * dist_y
u1 = u1 / np.linalg.norm(u1) * dist u1, u2 = get_u1_u2_affichage(u1, u2, bary, dist_x, dist_y, pb, pg)
u2 = u2 / np.linalg.norm(u2) * 1/2 * dist # print(u1, u2)
return u1, u2, x_range, y_range, dist return u1, u2, x_range, y_range
def visualiser_nuage(l_pts): def visualiser_nuage(l_pts):
bary = calc_barycentre(l_pts) bary = calc_barycentre(l_pts)
u1, u2 = diagonaliser_matrice22(calc_matrice_corrélation(l_pts))[:2] u1, u2 = get_info_affichage(l_pts)[:2]
dist = min(max(l_pts[:,0]) - bary[0], max(l_pts[:,1]) - bary[1])
u1 = u1 / np.linalg.norm(u1) * dist
u2 = u2 / np.linalg.norm(u2) * 1/2 * dist
ax = plt.axes() ax = plt.axes()
# plot du nuage # plot du nuage
plt.scatter(l_pts[:,0], l_pts[:,1]) plt.scatter(l_pts[:,0], l_pts[:,1])
ax.arrow(*bary, *u1, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") ax.arrow(*bary, *u1, ec="red", fc="white")
ax.arrow(*bary, *u2, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") ax.arrow(*bary, *u2, ec="orange", fc="white")
# ax.set_aspect('equal') # ax.set_aspect('equal')
plt.show() plt.show()
@ -103,10 +158,11 @@ def animation_nuage(l_pts, loops=10, time_sleep=2, delta_bruit=3):
fig.canvas.draw() fig.canvas.draw()
# nuage courant (pas de do while en Python) # nuage courant (pas de do while en Python)
bary = calc_barycentre(l_pts) bary = calc_barycentre(l_pts)
u1, u2, x_range, y_range, dist = get_info_affichage(l_pts) u1, u2 = get_info_affichage(l_pts)[:2]
u1l = np.linalg.norm(u1)
sc = ax.scatter(l_pts[:,0], l_pts[:,1]) sc = ax.scatter(l_pts[:,0], l_pts[:,1])
arr1 = ax.arrow(*bary, *u1, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") arr1 = ax.arrow(*bary, *u1, ec="red", fc="white")
arr2 = ax.arrow(*bary, *u2, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") arr2 = ax.arrow(*bary, *u2, ec="orange", fc="white")
plt.title("itération 0") plt.title("itération 0")
fig.canvas.flush_events() fig.canvas.flush_events()
fig.canvas.draw() fig.canvas.draw()
@ -119,15 +175,16 @@ def animation_nuage(l_pts, loops=10, time_sleep=2, delta_bruit=3):
l_pts += ran l_pts += ran
# recalcul des données # recalcul des données
bary = calc_barycentre(l_pts) bary = calc_barycentre(l_pts)
u1, u2, x_range, y_range, dist = get_info_affichage(l_pts) u1, u2, x_range, y_range = get_info_affichage(l_pts)
u1l = np.linalg.norm(u1)
ax.set_xlim(*x_range) ax.set_xlim(*x_range)
ax.set_ylim(*y_range) ax.set_ylim(*y_range)
# plot # plot
sc.set_offsets(l_pts) # repositionnement des points sc.set_offsets(l_pts) # repositionnement des points
arr1.remove() # on enlève les vecteurs arr1.remove() # on enlève les vecteurs
arr2.remove() arr2.remove()
arr1 = ax.arrow(*bary, *u1, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") arr1 = ax.arrow(*bary, *u1, ec="red", fc="white")
arr2 = ax.arrow(*bary, *u2, head_length=0.1*dist, head_width=0.1*dist, ec="black", fc="white") arr2 = ax.arrow(*bary, *u2, ec="orange", fc="white")
fig.canvas.flush_events() fig.canvas.flush_events()
fig.canvas.draw() # on redessine fig.canvas.draw() # on redessine
fig.canvas.flush_events() fig.canvas.flush_events()
@ -141,17 +198,19 @@ def main(argv):
gpi.add_argument("-i", "--input", gpi.add_argument("-i", "--input",
help="input file for dots - if none, generate dots") help="input file for dots - if none, generate dots")
gpi.add_argument("-f", "--function", gpi.add_argument("-f", "--function",
help="function to use to generate dots, ex -f 3*x+4") help="function to use to generate dots, ex -f \"3*x**2+cos(x)\"")
parser.add_argument("-N", "--nb-dots", type=int, default=500, parser.add_argument("-m", "--max-dot-xval", type=float, default=10,
help="number of dots to generate (from 0 to NB_DOTS) from function") help="x range of generated dots (from 0 to MAX_DOT_VAL, step=0.1) from function")
gps.add_argument("-s", "--show", action="store_true", gps.add_argument("-s", "--show", action="store_true",
help="show cloud of dots with u1 and u2") help="show cloud of dots with u1 and u2")
gps.add_argument("-l", "--loop", type=int, default=10, gps.add_argument("-l", "--loop", type=int,
help="number of loop to show/perform on randomized dots from originals ones") help="number of loop to show/perform on randomized dots from originals ones")
parser.add_argument("-g", "--generate-with-noise", action="store_true",
help="apply noise on dots generation")
parser.add_argument("-d", "--delay", type=float, default=2, parser.add_argument("-d", "--delay", type=float, default=2,
help="amount of time between each loop") help="amount of time between each loop")
parser.add_argument("-n", "--noise", type = float, default=10, parser.add_argument("-n", "--noise", type = float, default=10,
help="maximum value of the noise applied between each step") help="maximum value of the noise applied between each step and on generation if option -g and -f called")
if not argv: if not argv:
parser.print_usage() parser.print_usage()
sys.exit(0) sys.exit(0)
@ -164,10 +223,13 @@ def main(argv):
l_pts = acquérir_depuis_fichier(args.input) l_pts = acquérir_depuis_fichier(args.input)
else: else:
l_pts = [] l_pts = []
n = args.nb_dots # nombre de points n = args.max_dot_xval
f = lambda x: eval(args.function) # fonction génératrice de la ditribution f = lambda x: eval(args.function) # fonction génératrice de la ditribution
delta_bruit = 0 # bruit généré, 0 si on en veut aucun if args.generate_with_noise:
for i in range(n): delta_bruit = args.noise # bruit généré, 0 si on en veut aucun
else:
delta_bruit = 0
for i in np.arange(0, n, 0.1):
y = f(i) + choice((-1, 1)) * random() * delta_bruit/2 y = f(i) + choice((-1, 1)) * random() * delta_bruit/2
l_pts.append([i, y]) l_pts.append([i, y])
l_pts = np.array(l_pts) l_pts = np.array(l_pts)