Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GUI Python Discussion :

Matplotlib.pyplot - Flécher ses axes


Sujet :

GUI Python

  1. #1
    Futur Membre du Club
    Matplotlib.pyplot - Flécher ses axes
    Bonjour,

    Enseignant en mathématiques, on utilise la bibliothèque matplotlib pour faire nos affichages graphiques. (import matplotlib.pyplot as plt)
    Quelque chose me chagrine un peu dans l'affichage de graphiques, c'est l'absence de flèches au bout des axes. J'ai fait des recherches un peu partout, mais je n'ai pas trouvé de tutoriel ou de question sur un forum qui réponde à ce problème, et le peu de maîtrise que je possède en programmation m'empêche de farfouiller convenablement les librairies (que ce soit en efficacité de recherche ou en compréhension).

    Existe-t-il une méthode pour doter les axes d'une flèche ?

    Merci d'avance pour vos réponses

  2. #2
    Membre éclairé
    Bonjour,

    En cherchant avec les mots clefs "mathplotlib arrow axis" je suis tombé là dessus : https://matplotlib.org/api/_as_gen/m...xes.arrow.html .

    En espérant que celà correspond.

  3. #3
    Futur Membre du Club
    Merci pour la réponse, j'essaie de bidouiller et je montrerai ce que j'ai pu réussir à faire

  4. #4
    Futur Membre du Club
    Hello, j'ai essayé de mettre les flèches avec axis mais le problème qui se présente est que la flèche s'écrase soit à cause de la dimension de la fenêtre soit à cause de l'étendue des axes.
    Du coup j'ai trouvé un petit script pour régler ce problème et j'ai créé ces deux fonctions.

    Le truc qui est en conséquence moins satisfaisant, c'est que cela donne l'impression que les axes sont les axes du repères alors qu'en tapant tracéaxefléché(sin,-10,12,0.01) on voit que les axes ne passent pas par (0;0). C'est donc préférable de laisser à des élèves la config par défaut qui ne ressemble pas à des axes.
    Après une piste serait de rajouter un point symétrique du point extrémal de notre graphique par rapport à l'origine afin d'imposer à ce que l'origine du repère se trouve dans le graphique, et placer les flèches en conséquences. Si je trouve le courage de faire ça, je partagerai.

    Dernier petit bug de la flèche, cest quand on s'amuse à zoomer, à un moment la flèche traverse tout le graphique.


    Les deux fonctions :
    customisationidealebis : permet de régler la fenêtre avec les axes comme on veut.
    et mon tracéaxefléché qui permet de tracer la fonction f entre a et b, avec un pas de 0.01 (c'est mieux de mettre n points que de demander les pas quand on s'amuse à zoomer)

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    import matplotlib.pyplot as plt
     
    def tracéaxefléché(f,a,b,h=0.1,p=[]):
        #Trace la fonction f entre a et b avec un pas de 0.1, p pour afficher des points (donner l'abscisse)
        assert a<b
        n=int((b-a)/h)
        L=[a+h*i for i in range(n+1)]
        if b not in L:
            L.append(b)
        K=[f(i) for i in L]
    #Jusque là, on a juste de quoi ploté les antécédents et images
        customisationidealebis(a,b,min(K),max(K)) #appel de la deuxième fonction qui prend en arguments les points extrémaux du graphique pour ajouter les flèches
        plot(L,K,color='blue',lw=2)
    #Tout ce qui suit dans la fonction ça devrait faire hurler un informaticien tellement c'est de la débrouille, c'est simplement pour afficher des points optionnels sur le graphique, mais comme je maîtrisais pas encore les *args j'ai fait un mode plan B
        if type(p)!=type([]):
            plot(p,f(p),'o',color="black")
        else :
            M=[f(i) for i in p]
            plt.plot(p,M,'o',color='black') #Mettre '.' à la place de 'o' pour avoir des points plus discrets
        plt.grid(linestyle="--")
        plt.show()
     
     
     
    def customisationidealebis(xmin,xmax,ymin,ymax):
        h=(xmax-xmin)/50 #Pour créer un décalage des flèches par rapport aux extrémités qui vaut 1/50 de la taille de la fenêtre graphique
        H=(ymax-ymin)/50
        fig=plt.figure()
        ax = plt.gca()
        ax.spines['right'].set_color('none')
        ax.spines['top'].set_color('none')
        ax.xaxis.set_ticks_position('bottom')
        ax.spines['bottom'].set_position(('axes',0.02)) #'axes" impose de placer son axe sur une position entre 0 et 1 (zéro tout en bas, 1 tout en haut) 0.02 car 1/50
        ax.yaxis.set_ticks_position('left')
        ax.spines['left'].set_position(('axes',0.02)) #'data' permet de le centrer sur les données, ce qui est plus ou moins fait ici de manière qui pourait être jugée moche
        plt.axis([xmin,xmax,ymin,ymax])
        ##########
        # get width and height of axes object to compute
        # matching arrowhead length and width
        dps = fig.dpi_scale_trans.inverted()
        bbox = ax.get_window_extent().transformed(dps)
        width, height = bbox.width, bbox.height
     
        # manual arrowhead width and length
        hw = 1./20.*(ymax-ymin)
        hl = 1./20.*(xmax-xmin)
        lw = 1. # axis line width
        ohg = 0.3 # arrow overhang
     
        # compute matching arrowhead length and width
        yhw = hw/(ymax-ymin)*(xmax-xmin)* height/width
        yhl = hl/(xmax-xmin)*(ymax-ymin)* width/height
     
        # draw x and y axis
        ax.arrow(xmin, ymin+H, xmax-xmin, 0., fc='k', ec='k', lw = lw,
                 head_width=hw, head_length=hl, overhang = ohg,
                 length_includes_head= True, clip_on = False) 
    #Place les flèches au bon endroit, tous les arguments après les 4 premiers définissant les positions
    #copiés collés d'un script trouvé sur internet, car sans ça je n'arrivais pas à faire grand chose
     
        ax.arrow(xmin+h, ymin, 0., ymax-ymin, fc='k', ec='k', lw = lw,
                 head_width=yhw, head_length=yhl, overhang = ohg,
                 length_includes_head= True, clip_on = False)
     
    from math import sin
    tracéaxefléché(sin,-10,10,0.01)

###raw>template_hook.ano_emploi###