Grafica 2D folosind modulul pyplot din matplotlib

Matplotlib este o bibiloteca care permite generarea si afisarea unor obiecte grafice 2D si 3D. Modulul matplotlib.pyplot contine functii ce genereaza grafice de functii, vizualizeaza multimi de puncte, matrici ca imagini, bare, histograme, etc.

Pentru a afisa in IPython Notebook figurile generate prin rularea unei celule cod se da comanda magica:

In [1]:
%matplotlib inline

Apoi se importa modulul astfel:

In [2]:
import matplotlib.pyplot as plt

Orice functie din acest modul se apeleaza apoi ca plt.NumeFunctie.

Pe WEB gasiti numeroase exemple in care nu se importa matplotlib.pyplot, ci pylab, care este un modul ce combina functionalitatea modulelor matplotlib.pyplot si numpy intr-un singur namespace (este preferat de utilizatorii din domenii externe CS).

Generarea si afisarea unui grafic de functie

Pentru a genera graficul unei functii $f:[a,b]\to\mathbb{R}$ se procedeaza teoretic astfel:

  • se divizeaza intervalul $[a,b]$ in n intervale egale, cu pasul $h=(b-a)/n$.

  • Se evalueaza functia $f$ in punctele de diviziune $x_i=a+i*h$ ale intervalului $[a,b]$, si se noteaza $y_i=f(x_i)$, $i=\overline{0,n}$,

  • Graficul discretizat este reprezentat de punctele de coordonate $(x_i,y_i)$, $i=\overline{0,n}$.

  • functia plt.plot(x,y) avand ca argumente fie listele x,y de elemente $x_i$, respectiv $y_i$, fie array-urile 1D (vectorii) de elemente $x_i$, respectiv $y_i$, interpoleaza liniar punctele $(x_i,y_i)$ (uneste doua puncte consecutive printr-un segment), genereaza graficul si il afiseaza.

Pentru a genera graficul functiei $f(x)=e^{-x/8}\cos x$, pentru $x\in[0, 6\pi]$, divizam intervalul $[0,6\pi]$ prin $n=300$ puncte astfel:

In [3]:
import numpy as np
a=0
b=6*np.pi
n=300
x=np.linspace(a, b,n)
y=np.exp(-x/8)*np.cos(x)
plt.plot(x,y, 'r')
plt.title('Grafic de functie')
plt.xlabel('x')
plt.ylabel('y=f(x)')
Out[3]:
<matplotlib.text.Text at 0x7b34518>

O alta solutie este sa divizam intervalul $[a,b]$ precizand pasul de diviziune, h, nu numarul de puncte de diviziune:

In [4]:
a=-5
b=7
h=0.01
X=np.arange(a,b, h)
Y=-2*X*X+X+1
plt.plot(X,Y, 'g')
plt.title('Un arc de parabola')
Out[4]:
<matplotlib.text.Text at 0x7bff5f8>

Daca pasul de diviziune al intervalului nu este suficient de mic graficul unei functii derivabile nu este afisat neted, ci "cu colturi", deoarece functia plt.plot interpoleaza liniar doua puncte consecutive $(x_i, y_i)$, $(x_{i+1}, y_{i+1})$, adica traseaza segmentul care le uneste:

In [5]:
a=0
b=2*np.pi
h=0.5
xx=np.arange(a, b, h)
yy=np.sin(xx)
plt.plot(xx, yy)
Out[5]:
[<matplotlib.lines.Line2D at 0x7ec4eb8>]

Pe langa trasarea unor grafice, functia plt.plot poate realiza vizualizarea unui nor de puncte plasand cate un marker in pozitiile punctelor din nor.

Markere-le uzuale sunt 'o', '*', '.', 'x'. Ele pot fi inserate dupa codul culorii astfel:

In [6]:
x=np.random.random((1,10))
y=np.random.random((1,10))
plt.plot(x,y, 'b*')
Out[6]:
[<matplotlib.lines.Line2D at 0x7ef3128>,
 <matplotlib.lines.Line2D at 0x7ef3358>,
 <matplotlib.lines.Line2D at 0x7ef3550>,
 <matplotlib.lines.Line2D at 0x7ef36d8>,
 <matplotlib.lines.Line2D at 0x7ef3860>,
 <matplotlib.lines.Line2D at 0x7ef39e8>,
 <matplotlib.lines.Line2D at 0x7ef3b70>,
 <matplotlib.lines.Line2D at 0x7ef3cf8>,
 <matplotlib.lines.Line2D at 0x7ef3e80>,
 <matplotlib.lines.Line2D at 0x7ef7048>]

Apelul functiei matplotlib.pyplot.plot se realizeaza fie transmitandu-i doar argumente obligatorii, fie argumente si cuvinte cheie carora li s-au atribuit valori.

Atunci cand am prezentat sintaxa unei functii in Python am precizat doar ca o functie poate avea un numar de parametri, fara a intra in detalii relativ la natura argumentelor ce se transmit la apelul functiei.

Functia plt.plot este un exemplu de functie care ilustreaza concret diferitele posibilitati.

O functie in Python poate fi apelata, cu urmatoarele tipuri de argumente:

  • argumente obligatorii in numar fix sau variabil

  • argumente cuvinte cheie

Argumentele obligatorii sunt transmise unei functii in pozitie si ordine precisa.

De exemplu pentru functia plt.plot listele (sau array-urile 1D) x, y, de aceeasi lungime $n$, continand respectiv abscisele si ordonatele unor puncte, sunt argumente ce se transmit in aceasta ordine pentru a trasa graficul unei functii $y=f(x)$ sau pentru a marca punctele de coordonate $(x_i, y_i)$, $i=0, 1,\ldots, n-1$.

In locul primelor doua argumente, se poate transmite insa doar singur un argument pentru plt.plot si anume o lista (sau un array 1D), y. In acest caz lista absciselor este implicita, ea fiind lista indicilor, $0,1,2, \ldots, len(y)-1$, a elementelor din y:

In [7]:
y=[2,4,1,3,-2,5]
plt.plot(y)
Out[7]:
[<matplotlib.lines.Line2D at 0x830a1d0>]

Pentru a trasa un segment intre doua puncte de coordonate $(2,4)$, $(6,-1)$, constituim lista absciselor, x=[2,6], si respectiv a ordonatelor celor doua puncte, y=[4,-1]:

In [8]:
x=[2,6]
y=[4,-1]
plt.plot(x,y)
Out[8]:
[<matplotlib.lines.Line2D at 0x85c72b0>]

Un alt argument al functiei plt.plot este culoarea de trasare sau marcare a punctelor. Implicit culoarea este setata pe blue (a se vedea segmentul de dreapta de mai sus).

Culoarea de trasare/marcare se poate transmite in mai multe moduri:

  • precizand un caracter care este codul culorii:

'b', blue; 'g', green; 'r', red; 'c', cyan; 'm', magenta; 'y', yellow; 'k', black; 'w', white.

  • folosind cuvantul cheie color setat cu un tuple, color=(r, g, b) sau color=(r,g,b,alpha). Elementele celor 2 tuple-uri sunt subunitare si r,g,b indica cantitatea de red, green si blue din care este sintetizata culoarea. alpha indica transparenta culorii. Pentru alpha mai apropiat de 1, culoarea este mai opaca, iar mai apropiat de zero, mai transparenta.

  • folosind cuvantul cheie color setat cu un string ce reprezinta codul html al unei culori, color='#33FF99'

In [9]:
x=[2,4,3,1,5,0.7,6]
y=[1,3,2,2.41,2.5, 3.13, 2]

plt.subplot(1,4,1)
plt.plot(x,y, 'o', color=(0.86, 0.10, 0.46))
plt.subplot(1,4,2)
plt.plot(x,y, 'o', color=(0.86, 0.10, 0.46, 0.45))
plt.subplot(1,4,3)
plt.plot(x,y, 'o', color='#33FF99')
plt.subplot(1,4,4)
plt.plot(x,y,  color='k')
Out[9]:
[<matplotlib.lines.Line2D at 0x8f64fd0>]

In secventa de cod de mai sus apare functia plt.subplot(nrlin,nrcol, nrfig) care indica ca se vor genera/afisa mai multe figuri, plasate intr-o matrice cu nrlin linii si nrcol coloane.

nrfig indica a cata figura din cele nrlin*nrcol va fi generata. In exemplul de mai sus se genereaza 4 figuri plasate pe linie.

Inserarea marker-ului 'o' ca argument are ca efect afisarea unui cerc colorat in pozitia de coordonate $(x(i), y(i))$. Indicand un marker pentru puncte, punctele consecutive nu sunt unite de segmente. Suprimand marker-ul observam in figura 4 ca punctele sunt interpolate.

Cuvintele cheie sunt argumente optionale pentru o functie, care se transmit sub forma cuvantCheie=valoare. Argumentele cuvinte cheie se insereaza dupa argumentele pozitionale (cu pozitie fixa).

Dintre cuvintele cheie ce se pot transmite ca argumente functiei plt.plot amintim:

  • linestyle (tipul liniei ce se traseaza). linestyle sau simplu, ls, se poate seta ca fiind: solid, dashed, dotted
  • linewidth (grosimea liniei de trasare) sau scurt, lw, se poate seta cu un numar float ce reprezinta grosimea in puncte.
In [10]:
x=np.arange(0,5, 0.3)
y=x*x/8-x
plt.subplot(1,3,1)
plt.plot(x,y, lw=2, ls='dotted')
plt.subplot(1,3,2)
plt.plot(x,y, lw=3, ls='dashed')
plt.subplot(1,3,3)
plt.plot(x,y, 'r',  ls='solid', lw=4)
Out[10]:
[<matplotlib.lines.Line2D at 0x940bcf8>]

Cuvintele cheie se pot plasa in orice pozitie dupa argumentele obligatorii.

In modulul matplotlib.pyplot sunt definite si functii care manipuleaza imagini.

Array-urile 2D pot fi afisate ca imagini. Functiile de baza destinate imaginilor sunt:

plt.imread() incarca o imagine intr-un array

plt.imsave() salveaza un array intr-o imagine

plt.imshow() afiseaza imaginea

In [11]:
import matplotlib
X=np.random.random((16,16))# genereaza o matrice de tip 16x16 de elemente 
                           #aleator generate in intervalul [0,1)
img=plt.imshow(X,cmap=matplotlib.cm.spectral, interpolation='nearest')#afiseaza matricea ca o 
#imagine care rezulta realizand o corespondenta intre numerele din intervalul [0,1] si
#un colormap(paleta de culori)
In [12]:
X=plt.imread('Imag/Iony.png')
print 'Imaginea este de tip', X.shape
plt.imshow(X)
Imaginea este de tip (295L, 284L, 3L)
Out[12]:
<matplotlib.image.AxesImage at 0x98ca2b0>

matplotlib contine numeroase alte module care vor fi prezentate pe masura ce vor fi folosite.

Un script Python NumeScript.py care se ruleaza din linia de comanda sau in Spyder si apeleaza functii din matplotlib.pyplot va afisa figura generata doar daca la sfarsitul script-ului se insereaza functia plt.show(). Altfel figura desi generata, nu este afisata.

Un exemplu de astfel de script este urmatorul:

In [13]:
import numpy as np
import matplotlib.pyplot as plt
t=np.arange(0,4, 0.01)
x=np.exp(-t)*np.cos(2*np.pi*t)
y=np.exp(-t)*np.sin(2*np.pi*t)
plt.plot(x,y,'r')
plt.axis('equal')
plt.xlabel('x(t)')
plt.ylabel('y(t)')
plt.show()

Daca copiati liniile de cod din celula precedenta si le salvati intr-un fisier spirala.py si comentati linia plt.show() veti vedea ca la rulare nu este afisat nici un mesaj de eroare, dar figura nu este vizualizata. Decomentand plt.show() va apare figura de mai sus.

In [1]:
from IPython.core.display import HTML
def  css_styling():
    styles = open("./custom.css", "r").read()
    return HTML(styles)
css_styling()
Out[1]: