Doç. Dr. Özgür Baştürk
Ankara Üniversitesi, Astronomi ve Uzay Bilimleri Bölümü
obasturk at ankara.edu.tr
http://ozgur.astrotux.org
Python’da grafik çizdirmek için $matplotlib$ kütüphanesinde yer alan ve $matplotlib$ ’in $MATLAB$ stilinde grafik üretmesini sağlayan komutların bir koleksiyonu olarak tanımlanabilecek $matplolib.pyplot$ modülü sıklıkla kullanılmaktadır. Matplotlib kütüphanesinin bazı çok önemli avantajlarının bulunması sebebiyle kullanımı oldukça yaygındır. Bu önemli avantajlar:
olarak sıralanbilir. Matplotlib oldukça hacimli bir modül olup, hakkında geniş bilgiye http://matplotlib.org/ adresinden ulaşılabilir.
Aşağıdaki kod parçasında basit bir örnek görülmektedir.
from matplotlib import pyplot as plt
# matplotlib grafiklerinin juypyter'da goruntulenebilmesi icin
# %matplotlib inline sihirli kelimesi (ing. magic keyword) verilmelidir
%matplotlib inline
plt.plot([1,2,3,4])
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Gördüğünüz grafik yukarıdaki Python kodunun çıktısıdır. İstediğiniz formatta kaydedip saklayabilir, ya da üzerinde istediğiniz bölümüne yaklaştırma (ing.zoom-in) ya da uzaklaştırma (ing. zoom-out) yapabilirsiniz. Ancak bu tür işlemler için ilgili jupyter "sihirli" kelimesini inline komutu ile değil notebook komutuyla kullanmanız gerekir.
Yukarıdaki kod parçasında $PyPlot$'un $plot$, $xlabel$ ve $ylabel$ fonksiyonları sırasıyla bir grafik (tek bir dizi (liste ya da demet) verildiğinde, $y$-ekseni değeri olarak alınır, $x$-ekseninin varsayılan listesi 0'dan başlar ve $y$-eksenini oluşturan dizi kadar eleman içerir), $x$ ve $y$ eksenleri için birer başlık nesnesini varsayılan parametrelerle oluşturur. $show()$ metodu ise onu ekrana getirir!
Çizdirilmek istenen grafik iki eksen (x ve y eksenleri) için ayrı ayrı tanımlanan iki veri grubu üzerinden çizilecekse her iki eksene ilişkin veri sağlanmalıdır.
# sembol turunu mavi bir cizgi yerine
# kirmizi (r) bir ici dolu daire (o) olarak tanimlayalim
plt.plot([1,2,3,4], [1,4,9,16], 'ro')
# x ve y eksenlerini daha iyi bir gorunum icin sinirlayalim
#plt.axis([0, 6, 0, 20])
# sadece tek bir eksende limit de belirleyebilirsiniz
plt.ylim((0.,20.))
plt.show()
Görüldüğü üzere grafiğin eksen limitlerini belirlemek üzere $axis$ metodunu kullandık. Alternatif olarak $plt.xlim((0,6))$ ve $plt.ylim((0,20))$ şeklinde demet (ya da istenirse liste) nesneleriyle limitlerin tanımlandığı iki metod da kullanılabilir. $plot$ ifadesinde "$ro$" şeklinde bir metinle verilen ise noktaların şeklini "o" rengini kırmızı (red) belirleyen bir parametredir. "$b+$" aynı şekilde noktaları mavi birer "$+$" işareti ile gösterecektir (deneyiniz!).
$PyPlot$ modülünde birkaç eğriyi aynı anda tek bir grafik üzerine çizdirebilmek için grafikleri sırayla çizdirip, en sonunda göstermek ($show()$) üzere yapılması gereken bir şey yoktur.
import numpy as np
# 0 ile 5 arasinda 0.2 esit araliklarla ayrilmis noktalarimiz olsun
t = np.arange(0., 2., 0.2)
# Asagidaki her bir grafigi farkli bir renk ve sembolle gosterelim
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Eğrilerin düzgün görünmesi için nokta sıklığına dikkat edilmesi gerekir. Zira matplotlib noktaları doğru ile birleştirerek eğri çizilmesine olanak sağlar.
import numpy as np
# 0 ile 5 arasinda 0.5 esit araliklarla ayrilmis noktalarimiz olsun
t = np.arange(0., 2., 0.5)
plt.plot(t, t, 'r-')
plt.plot(t, t**2, 'b-')
plt.plot(t, t**3, 'g-')
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Ancak $PyPlot$ modülü ile birkaç grafiği aynı şekil (pencerenin) farklı yerlerine çizdirilmek istendiğinde subplot() fonksiyonundan yararlanmak gerekir. Fonksiyona çzidirilmek istenen grafiğin hangi satır ve sütünde oluşturulacağı ve oluşturulan kaçıncı grafik olduğu bilgisi argüman olarak verilir.
def f(t):
return np.exp(-t) * np.cos(2*np.pi*t)
t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)
plt.figure(1)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()
Burada $figure(1)$ bir şekil nesnesi oluşturmak için kullanılan bir metottur. $subplot$ ise her bir grafik için şekil üzerinde bir grafik nesnesi oluşturur. ($211$) bu şekil nesnesi üzerinde $2.$ satır ve $1.$ sütunda grafik oluşturacağımızı, bu grafiğin $1$ numaralı grafik olduğunu, $(212$) ise bu grafiğin $2.$ satır $1.$ sütundaki $2$ numaralı grafik olduğunu göstermektedir. Eğer bu grafikleri bir satır ve iki sütunda oluşturmak isteseydik birncisini ($121$), ikincisini ($122$) ile oluşturmamız gerekecekti. Gördüğünüz gibi "$k$" siyah renk için kullanılmakta, sembol türü için herhangi bir tercih yapılmadığında kesiksiz bir eğri, "$--$" kullanıldığında ise kesikli bir eğri çizdirilmektedir.
$PyPlot$ modülünde birkaç eğriyi aynı anda farklı iki şeklin (çerçeve) farklı yerlerine de çizdirebilirsiniz.
# birinci sekil
plt.figure(1)
# ilk grafik
grafik1 = plt.subplot(121)
grafik1.plot([1,2,3])
# ikinci grafik
grafik2 = plt.subplot(122)
grafik2.plot([4,5,6])
# ikinci sekil, ilk grafik varsayilan olarak (111)
plt.figure(2)
grafik3 = plt.plot([4,5,6])
# birinci sekil ikinci grafigin basligini belirleyelim
plt.figure(1)
plt.title('Python Ogreniyorum')
grafik1.set_xlabel("x")
# grafiklerimizi gosterelim
plt.show()
$Pyplot$ grafikleri üzerinde metin yönetimi oldukça kolaydır. Başlıklar, $title$, $xlabel$ ve $ylabel$ fonksiyonları ile yönetilirken, grafiğin herhangi bir yerine metin $text$ fonksiyonu ile $(x,y)$ koordinatları grafik biriminde verilerek yerleştirilir. $text$ fonksiyonu $\LaTeX$ sembolleri kullanabilmek de dahil olmak üzere pek çok özellik sağlar.
# Bir Histogram cizmek uzere verimizi olusturalim
# Ortalama (mu) ve standart sapma (sigma)
# degerlerimizi verelim
mu, sigma = 100, 15
# np.random fonksiyonu randn ile 10000 tane
# rastgele sayidan olusan bir dizi yaratalim
iq = mu + sigma * np.random.randn(10000)
# verimizden bir histogram olusturalim
n, bins, patches = plt.hist(iq, 50, density=1,
facecolor='g', alpha=0.75)
# x eksenine bir baslik verelim
plt.xlabel('IQ')
# y eksenine bir baslik verelim
plt.ylabel('Olasilik')
# grafigimize bir baslik verelim
plt.title('IQ Histogrami')
# ortalama ve standart sapmayi gosterelim
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
# eksen sinirlarimizi belirleyelim
plt.xlim((40,160))
plt.ylim((0,0.03))
# grid (izgara) gosterelim
plt.grid(True)
plt.show()
$PyPlot$ grafiklerinde grafikteki noktalarınızı $annotate$ fonksiyonunu kullanarak etiketleyebilirsiniz.
# t eksenini numpy arange fonksiyonu ile olusturalim
t = np.arange(0.0, 5.0, 0.01)
# s = cos(2 * PI * t) ifadesiyle fonksiyonumuzu olusturalim
cost = np.cos(2*np.pi*t)
# grafigimizi cizdirelim
plt.plot(t, cost, lw=2)
# noktamizi etiketleyelim
plt.annotate('yerel maksimum', xy=(2, 1), xytext=(3, 1.5),
arrowprops=dict(facecolor='black', shrink=0.05),)
# y ekseninin limitlerini belirleyelim
plt.ylim(-2,2)
plt.show()
Çizilen bir grafik üzerinde istenilen her veri grubu ayrı bir etiketle (ing. legend) gösterilerek grafiğe bakan kişinin daha kolay anlamasına yardımcı olanabilir. Bu işlem $legend$ fonksiyonuyla gerçekleştirilir.
from matplotlib import pyplot as plt
import numpy as np
x = np.linspace(0,2*np.pi,100)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y1,"b-", label="sinus")
plt.plot(x,y2,"r-", label="kosinus")
plt.xlabel("x")
plt.ylabel("y")
plt.legend(loc="best")
plt.show()
Görüldüğü üzere her bir grafiğe $label$ argümanı üzerinden verilen etiketler, $legends$ fonksiyonunun etiketlerin grafiğin neresine yerleştirileceğini belirleyen $location$ (kısaca $loc$) parametresi üzerinden belirlenen yere yerleştirilmektedir. $loc$ aşağıdaki seçeneklerden biri olabilir:
Ayrıca koordinatlar üzerinden istenen koordinatlara da koymak mümkün olduğu gibi pek çok başka seçenek ve ayar da bulunmaktadır.
# x ve y eksenleri birer liste olarak olusturulmus olsun
x = [-7.30000, -4.10000, -1.70000, -0.02564,
1.50000, 4.50000, 9.10000]
y = [-0.80000, -0.50000, -0.20000, 0.00000,
0.20000, 0.50000, 0.80000]
plt.plot(x,y,'ro')
plt.show()
Gözlemsel hataları çizdirebilmek için $pyplot.errorbar$ fonkisyonu kullanılır.
# x ve y eksenleri birer liste olarak olusturulmus olsun
x = [-7.30000, -4.10000, -1.70000, -0.02564,
1.50000, 4.50000, 9.10000]
y = [-0.80000, -0.50000, -0.20000, 0.00000,
0.20000, 0.50000, 0.80000]
xhata = np.ones(len(x))*0.5
yhata = np.ones(len(y))*0.1
plt.errorbar(x,y,xerr=xhata,yerr=yhata,fmt=".")
plt.show()
# x ve y eksenleri birer liste olarak olusturulmus olsun
x = [-7.30000, -4.10000, -1.70000, -0.02564,
1.50000, 4.50000, 9.10000]
y = [-0.80000, -0.50000, -0.20000, 0.00000,
0.20000, 0.50000, 0.80000]
# NumPy polyfit fonksiyonuna x ve y degerlerini
# ve dogru uyumlayacagimizi (1) soyleyelim
katsayilar = np.polyfit(x, y, 1)
# Isterseniz katsayilari kullanarak da dogru uyumlamanizi
# verinizin uzerine cizdirebilirsiniz.
#print(katsayilar[0])
#yfit = katsayilar[0]*np.array(x) + katsayilar[1]
#plt.plot(x,yfit,'b-')
#plt.show()
#print("{:.2f}x + {:.2f}".format(katsayilar[0], katsayilar[1]))
# polyfit polinom katsayilarini hesaplar bu katsayilari poly1d'ye
# verilirse bulunan katsayilara gore bir polinom fonksiyonu
# yaratilir. x degerlerine denk gelen dogrusal y degerleri
# hesaplanir
polinom = np.poly1d(katsayilar)
y_polinom = polinom(x)
print("Polinomun katsayilari: ", katsayilar)
print("Polinom: ", polinom)
plt.plot(x, y, 'o')
plt.plot(x, y_polinom)
plt.ylabel('y')
plt.xlabel('x')
plt.xlim(-10,10)
plt.ylim(-1,1)
plt.show()
Şimdi de gözlemsel veriye 6. dereceden bir eğri uyduralım.
# x'e karsilik y seklinde gozlemsel veri:
x = [2.53240, 1.91110, 1.18430, 0.95784, 0.33158,
-0.19506, -0.82144, -1.64770, -1.87450, -2.2010]
y = [-2.50400, -1.62600, -1.17600, -0.87400, -0.64900,
-0.477000, -0.33400, -0.20600, -0.10100, -0.00600]
# 6. dereceden polinom fitinin katsayilari
katsayilar = np.polyfit(x, y, 6)
polinom_6 = np.poly1d(katsayilar)
# 0.1 araiklarla yeni bir x ekseni
x_polinom6 = np.linspace(x[0], x[-1], 1000)
y_polinom6= polinom_6(x_polinom6)
# Grafik cizimi
plt.plot(x, y, 'o')
plt.plot(x_polinom6, y_polinom6,'-.')
plt.ylabel('y')
plt.xlabel('x')
print(polinom_6)
plt.show()
Aşağıda verilen tüm dekorasyon parametrelerinin kombinasyonlarını da kullanabilirsiniz. Örneğin "$kx$" siyah renkli çarpı işaretleri, "$m--$ mor" (magenta) renkli kesikli eğri anlamına gelir!
Grafiklerinizi dekore etmek üzere aşağıdaki renklere ingilizce isimlerinin baş harfleriyle ulaşabilirsiniz:
Sarı: “y” ,
Mor: “m” ,
Açık mavi: “c”,
Kırmızı: “r” ,
Mavi: “b” ,
Beyaz: “w” ,
Siyah: “k”
Tüm renkler için bkz.
Grafiklerinizde kullanacağınız eğrilere aşağıdaki stilleri uygulayabilirsiniz:
Kesiksiz Eğri: "-" (varsayılan),
Kesikli Eğri: "--",
Noktalı Eğri: ":",
Kesikli Noktalı Eğri: "-."
Grafiklerinizde kullanacağınız noktalara aşağıdaki stilleri uygulayabilirsiniz:
Artı işareti "+",
İçi dolu yuvarlak: "o",
Yıldız "*",
Nokta: ".",
Çarpı işareti: "x" ,
İçi dolu kare: "s" ,
İçi dolu baklava dilimi: "d" ,
Bir köşesi yukarıya bakan üçgen: "^",
Bir köşesi aşağıya bakan üçgen: "v",
Bir köşesi sağa bakan üçgen: ">",
Bir köşesi sola bakan üçgen: "<",
Beş köşeli yldız (pentagram): "p",
Altı köşeli yıldız (hexagram): "h"
Matplotlib, $figsize$ ve $dpi$ argümanları kullanılarak bir şekil nesnesi oluşturulduğunda en boy oranının (ing. aspect ratio), inç başına nokta sayısı (Dot per Inch, DPI) biriminde çözünürlük ve şekil boyutunun belirlenmesine izin verir. $figsize$, şeklin inç cinsinden genişlik ve yüksekliğini belirleyen bir demet değişkene (tuple) atanabilir. Örnepin 800x600 piksel, 100 nokta / inç rakam oluşturmak için aşağıdaki kod kullanılabilir.
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
fig = plt.figure(figsize=(8,6), dpi=100)
x = np.linspace(0,2*np.pi,100)
y = np.sin(x)
plt.plot(x,y,"b-")
plt.xlabel("x")
plt.ylabel("sin(x)")
plt.suptitle("Sinus Fonksiyonu")
plt.title("14 Aralik 2020, Pazartesi")
plt.show()
Oluşturduğunuz bir şekli istediğiniz bir formatta otomatik olarak bir dosyaya kaydetmek isterseniz bunu matplotlib.pyplot modülünün $savefig$ fonksiyonuyla kolaylıkla yapabilirsiniz. Örneğin bir önceki kod parçasıyla oluşturulan sinüs fonksiyonunun görüntüsünü oluşturulan büyüklükte ve “Portable Graphics Format" (PNG) formatında kaydetmek için aşağıdaki kodu yazmak yeterlidir.
Şekliniz bu durumda kodu çalıştırdğınız klasöre kaydedilir. Eğer başka bir klasöre kaydetmek isterseniz, bu durumda söz konusu klasörün nerede olduğunu göreli (relative path) ya da mutlak (absolute path) olarak tanımlamanız gerekir.
fig.savefig("sinus_fonksiyonu.png")
Matplotlib, PNG, JPG, EPS, SVG, PGF ve PDF gibi çeşitli formatlarda yüksek kaliteli çıktılar üretebilir. Bilimsel makaleler için, mümkün olduğunda EPS ya da PDF kullanmanızı öneririm. (Pdflatex ile derlenen LaTeX belgeleri $includegraphics$ komutu kullanılarak PDF'ler içerebilir). Dosya türünü sadece uzantıyla kontrol edebildiğiniz gibi dosya türlerinin ilgili özellikleri de bu fonksiyonla kontrol edilebilir; ancak bu dersin kapsamı dışındadır.
Grafiğin eksenlerini $zaman (s)$ ve $yukseklik (m)$, başlığını $Dikey Atis Problemi$ olarak adlandırınız.
Fahrenheit dereceden Santigrad dereceye hızlı bir dönüşüm C = (F - 30) / 2 formülüyle yapılabilir. $[20, 120]$ kapalı aralığında birbirinden eşit uzaklıkta 250 adet Fahrenheit derece değerini, bu formülle ve standart dönüşüm formülüyle (C = 9 / 5 * (F - 32) + 180) Santigrad dereceye dönüştürünüz. Oluşan Santigrad derece değerlerini, Fahrenheit dereceye karşılık çizdirerek (standart dönüşüm mavi kesiksiz doğru, yaklaşık dönüşümü kırmızı noktalı-kesikli doğru) yaklaşık formülün başarısını karşılaştırma yoluyla test ediniz.
Bir önceki soruda oluşturulan grafikte görüldüğü gibi hesaplanan iki ifade belirli bir Fahrenheit değerinde eşit olmakta (doğrular kesişmekte) ve yaklaşık ifade ile hesaplanan değerler, tam ifade ile hesaplananlardan giderek uzaklaşmaktadır. Her iki doğrunun kesiştiği değeri bularak, grafik üzerinde yeşil, içi dolu bir kare ile gösteriniz.
$V_0$ hızı ile yatayla $\theta$ açı yapacak şekilde $g$ yerçekim ivmeli ortamda fırlatılan bir cismin izleyeceği yol aşağıdaki formülle verilir.
Verilen bu ifadeyi $yatay\_atis$ adında bir fonksiyon olarak kodlayınız. $g = 9.81$ ve $y_0 = 0$ parametrelerini bu varsayılan değerlerle anahtar kelime argümanları olarak, diğer tüm parametreleri ($x$, $\theta$, $V_0$) ise konum argümanı olarak alınız.
Burada, x cismin yatay eksendeki koordinatı, y ise yüksekliğidir. $x \in [0, \frac{V_{0}^2 sin 2 \theta}{g}]$ aralığında oluşturacağınız a) 10 $x$ değeri için ($x_1$) cismin aldığı yolu (x'e karşılık y) kırmızı kesiksiz doğru, b) 100 $x$ değeri için ($x_2$) ise yeşil noktalı doğru ile çizdiriniz. $V_0 = 10$ m/s, $\theta = \pi / 6$ radyan alınız.
Cismin maksimum yüksekliğe çıktığı andaki x koordinatını ($xmax$) $\frac{V_0^2 sin 2\theta}{2 g}$ formülünden hesaplattıktan sonra $yatay\_atis$ fonksiyonunuzda yerine koyarak y koordinatını ($ymax$) bulunuz ve grafiğinizde bu ($xmax$, $ymax$) koordinatını mavi bir baklava dilimi (ing. diamond) işareti ile işaretleyiniz.