(primer izrisa Toka in Naboja kot funkcije časa)
Dejan Križaj, 2019
Namen: Z izvajanjem in študijem primerov v tem zvezku se boste naučili uporabljati Jupyter zvezek za izračune funkcij in različne načine njihove grafične predstavitve.
(Po potrebi poglej https://colab.research.google.com/notebooks/welcome.ipynb za osnovne informacije o uporabi Colab-a.)
Sproti rešuj male "programerske" izzive in se nauči dela z Jupytrom.
Želimo narediti niz vrednosti in izračunati funkcijo za te vrednosti. Na primer, niz (ali vektor) z vrednostmi od 0 do 5 naredimo preprosto takole:
x=[0,1,2,3,4]. Ta izraz lahko preiskusiš tako, da narediš novo celico (klikneš +Code) in zaženeš z Ctrl-Enter. Izgleda, kot da se ni zgodilo nič, v resnici se je ukaz izvedel in v x so spravljene vrednosti kot zapisano. To lahko preveriš tako, da pod to vrstico napišeš x ali display(x) ali print(x) in izpisala se bo vrednost x-a. Nize (vektorje) naredimo pogosto z ukazi kot npr. y=range(4). Toda pozor: python začne šteti z 0 in ne 1. Range(4) torej naredi niz štirih vrednosti, 0,1,2,3. Vrednost posameznega elementa v nizu dobimo z y[indeks], kjer ima lahko indeks vrednosti od 0 do 3. Lahko uporabimo tudi ukaz arange iz modula Numpy, npr. z=np.arange(0,11,2), ki naredi niz od 0 do 10 s korakom 2. Podoben je ukaz s=np.linspace(0,10,6), ki naredi niz od 0 do 10 razdeljen na 6
števil z enakim razmikom. Na nizih lahko delamo enake operacije, kot bi jih delali s številom. Npr. ukaz p=2*s+3 pomnoži vse vrednosti niza s z 2 in jim prišteje 3.
In še beseda o matematičnih funkcijah. Običajno jih vsebuje modul Numpy. Npr. np.pi vrne vrednosti $\pi$, np.sin(x) vrne sinus x-a, np.exp(x) vrednost(i) eksponentne funkcije, itd. Če je x niz, bo niz tudi rezultat operacije.
# Če poznaš osnove nizov, boš to preskočil
# To je komentar, izpisi ukaza print so v naslednji celici
# Različni načini kreiranja nizov
x=[0,1,2,3,4]
print(x) # izpiše [0, 1, 2, 3, 4]
y=range(4)
print(y)
print(y[3]) # izpiše četrto vrednost v nizu, saj začne python šteti od 0 in ne od 1
import numpy as np # vnos modula numpy, ukaze se naslavlja z np.ukaz
y=np.arange(5) # podobno kot range, samo s knjižnico numpy
display(y) # isto kot print
z=np.arange(0,11,2) # niz od 0 do 11 po koraku 2
print(z)
s=np.linspace(0,10,6) # niz od 0 do 10 s 6 vrednostmi, rezultat torej [ 0 2 4 6 8 10]
print(s)
p=2*s+3 # vse vrednosti v nizu pomnožimo z 2 in prištejemo 3
print(p)
a=np.sin(x) # sinus pač, x je v radianih
print(a)
b=np.exp(x) # eksponentna funkcija ...
print(b)
[0, 1, 2, 3, 4] range(0, 4) 3
array([0, 1, 2, 3, 4])
[ 0 2 4 6 8 10] [ 0. 2. 4. 6. 8. 10.] [ 3. 7. 11. 15. 19. 23.] [ 0. 0.84147098 0.90929743 0.14112001 -0.7568025 ] [ 1. 2.71828183 7.3890561 20.08553692 54.59815003]
Zdaj pa ti:
Jupyter je zasnovan na programskem jeziku Python. Za matematične operacije pogosto uporabljamo knjižnico Numpy, za izrise pa knjižnico Matplotlib. Pred začetkom dela je potrebno v kodo vnesti knjižnice (module), ki jih želimo uporabljati.
Za primer bomo vzeli elektrenje kondenzatorja s tokom. Izkaže se, da je to elektrenje eksponentna funkcija, odvisna od časovne konstante $\tau=RC$.
Izrisali bomo naboj kot funkcijo časa
$Q(t) = 5\left( {1 - {e^{ - \frac{t}{{10{\rm{\: s}}}}}}} \right){\rm{mC}}$
ter tok kot odvod naboja po času
$i(t) =\frac{d Q}{dt}=0.5{e^{-t/10 \: \rm s}} \: \rm mA $
# vnos potrebnih knjižnic, matplotlib za grafe in numpy za matematične operacije
#%matplotlib inline # potreben ukaz, da se slike izrišejo v notebooku
# ko smo enkrat knjižnico (modul) zagnali z ukazom import, to velja za vse celice v zvezku
import matplotlib
import matplotlib.pyplot as plt
import numpy as np # np bo okrajšava za ukaze iz knjižnice numpy
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1) # np. pomeni, da gre za uporabo funkcije iz knjižnice numpy
# Izračun naboja
Q = 5*(1-np.exp(-t/10))
# Priprava slike
plt.figure() # plt. pomeni, da gre za uporabo knjižnice matplotlib
plt.plot(t, Q) # izris, kje kjer je t na X osi in Q na Y osi
# oblikovanje slike
plt.xlabel('Čas (s)')
plt.ylabel('Naboj (mC)')
plt.title('Naboj v odvisnosti od časa')
plt.show()
Subplot omogoča več načinov izrisa in naslavljanja grafov.
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1)
# Izračun naboja
Q = 5*(1-np.exp(-t/10))
# Priprava slike
fig, ax = plt.subplots()
ax.plot(t, Q)
ax.set(xlabel='čas (s)', ylabel='Naboj (mC)', # Označitev osi
title='Naboj v odvisnosti od časa')
ax.grid()
plt.show()
Zdaj pa ti:
# vnos knjižnic in izračun naboja smo opravili že v prejšnji celici
# dodamo še izračun toka
i=0.5*np.exp(-t/10)
# Priprava slike
fig, ax = plt.subplots()
ax.plot(t, Q, label="$Q(t)$") # oznake so lahko LaTex oblike
ax.plot(t, i, label="$i(t$)")
# pozicioniranje legende
ax.legend(bbox_to_anchor=(0.8,.5), loc='upper left', borderaxespad=0.)
ax.set(xlabel='čas (s)', ylabel='Naboj in Tok',
title='Naboj in tok v odvisnosti od časa')
ax.grid()
plt.show()
Zdaj pa ti:
V prejšnjem primeru smo izrisali obe krivulji na istem grafu. Ker imata tok in naboj različne enote, je bolj primerno izrisati vsako krivuljo na svoji osi. Ena varianta je, da izrišemo na istem grafu dve krivulji vendar z različnima ordinatnima osema.
fig, ax1 = plt.subplots()
color = 'tab:red'
ax1.set_xlabel('Čas (s)')
ax1.set_ylabel('Naboj (mC)', color=color)
ax1.plot(t, Q, color=color)
ax1.tick_params(axis='y', labelcolor=color)
ax1.grid(axis='x')
ax1.text(2, 2, r'$Q(t)$', fontsize=12) # dodamo tekst na pozicijo x=2, y=2. Tekst je v obliki Latex formule, ker je znotraj $$
ax2 = ax1.twinx() # x os za drugi plot naj bo enaka x osi prvega plota
color = 'tab:blue'
ax2.set_ylabel('Tok (mA)', color=color)
ax2.plot(t, i, color=color)
ax2.tick_params(axis='y', labelcolor=color)
plt.show()
Zdaj pa ti:
Namesto na enem grafu z dvema različnima osema narišimo krivulji v dveh grafih, npr. enega pod drugim. Pri tem dodamo še eno x os z manj točkami, ki omogoča izris krivulje in simbolov na krivulji. (Če bi izrisali simbole na originalni x osi, bi se prekrivali in bi delovalo kot ena debela črta. Če pa bi izrisali funkcijo le v malo točkah, ne bi delovala dovolj zvezno.)
t1 = np.arange(0.0, 30.0, 5)
# Izračun naboja in toka v manj točkah
Q1= 5*(1-np.exp(-t1/10))
i1= 0.5*np.exp(-t1/10)
plt.figure()
plt.subplot(211)
plt.plot(t, Q, 'k', t1, Q1, 'bo')
plt.ylabel('Naboj (mC)')
plt.title('Naboj in tok v odvisnosti od časa')
plt.grid()
plt.subplot(212)
plt.plot(t, i, 'k', t1, i1, 'bo')
plt.ylabel('Tok (mA)')
plt.xlabel('čas (s)')
plt.grid()
plt.show()
Zdaj pa ti:
t1 = np.arange(0.0, 30.0, 5)
# Izračun naboja in toka v manj točkah
Q1= 5*(1-np.exp(-t1/10))
i1= 0.5*np.exp(-t1/10)
plt.figure(figsize=(15, 8))
plt.subplot(121)
plt.plot(t, Q, 'k', t1, Q1, 'bo')
plt.xlabel('čas (s)')
plt.ylabel('Naboj (mC)')
plt.title('Naboj v odvisnosti od časa')
plt.grid()
plt.suptitle('Graf naboja na levi in toka na desni')
plt.subplot(122)
plt.plot(t, i, 'k', t1, i1, 'bo')
plt.ylabel('Tok (mA)')
plt.xlabel('čas (s)')
plt.grid()
plt.show()
Pogosto nas zanima, kako določen parameter vpliva na spremembo oblike krivulje. Obstaja več načinov, kako to narediti.
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1)
# Izračun naboja
Q = 5*(1-np.exp(-t/10))
Q2 = 5*(1-np.exp(-t/5))
Q3 = 5*(1-np.exp(-t/1))
# Priprava slike
plt.figure()
plt.plot(t, Q,label='Q1')
plt.plot(t, Q2,label='Q2')
plt.plot(t, Q3,label='Q3')
plt.xlabel('čas (s)')
plt.ylabel('Naboj (mC)')
plt.title('Naboj v odvisnosti od časa')
plt.legend()
plt.show()
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1)
# Naboj kot funkcija
def Q(tau):
return 5*(1-np.exp(-t/tau))
tau=[10,5,1] # niz treh vrednosti tau
labela=['Q1','Q2','Q3'] # niz treh oznak
plt.figure()
# Zanka, ki se izvrši večkrat in iterira (povečuje) indeks i
for i in range(3):
plt.plot(t, Q(tau[i]),label=labela[i])
plt.xlabel('čas (s)')
plt.ylabel('Naboj (mC)')
plt.title('Naboj v odvisnosti od časa')
plt.legend()
plt.show()
Zdaj pa ti:
Za osnovno delo z grafi si poglej spletno stran https://matplotlib.org/3.1.1/tutorials/introductory/pyplot.html#sphx-glr-tutorials-introductory-pyplot-py
(kodo lahko spreminjate v tem zvezku (notebooku) ali pa kreirate novega z File/New Python 3 Notebook in preizkušate različne variante izrisov)
Primeri iz Codelaba: https://colab.research.google.com/notebooks/charts.ipynb#scrollTo=WALI8x49GUpe
## Niz vrednosti x in y
x=np.linspace(0,2*np.pi,20)
y=2*np.sin(x)
print(x,y)
[0. 0.33069396 0.66138793 0.99208189 1.32277585 1.65346982 1.98416378 2.31485774 2.64555171 2.97624567 3.30693964 3.6376336 3.96832756 4.29902153 4.62971549 4.96040945 5.29110342 5.62179738 5.95249134 6.28318531] [ 0.00000000e+00 6.49398938e-01 1.22842543e+00 1.67433296e+00 1.93880053e+00 1.99316899e+00 1.83154665e+00 1.47144782e+00 9.51894786e-01 3.29189181e-01 -3.29189181e-01 -9.51894786e-01 -1.47144782e+00 -1.83154665e+00 -1.99316899e+00 -1.93880053e+00 -1.67433296e+00 -1.22842543e+00 -6.49398938e-01 -4.89858720e-16]
# Izris dodatnih pik na krivulji
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1)
t1 = np.arange(0.0, 30.0, 5)
# Izračun naboja
Q = 5*(1-np.exp(-t/10))
Q1= 5*(1-np.exp(-t1/10))
# Priprava slike
fig, ax = plt.subplots()
ax.plot(t, Q)
ax.plot(t1,Q1,'o')
ax.set(xlabel='čas (s)', ylabel='Naboj (mC)', # Označitev osi
title='Naboj v odvisnosti od časa')
ax.grid()
plt.show()
# mali programerski izziv - tekstovna označitev krivulj
i=0.5*np.exp(-t/10)
fig, ax1 = plt.subplots()
ax1.set_xlabel('Čas (s)')
ax1.set_ylabel('Naboj (mC)')
ax1.plot(t, Q)
ax1.tick_params(axis='y')
ax1.grid(axis='x')
ax1.text(t[15], Q[10], r'$Q(t)$', fontsize=12)
ax2 = ax1.twinx() # x os za drugi plot naj bo enaka x osi prvega plota
ax2.set_ylabel('Tok (mA)')
ax2.plot(t, i)
ax2.tick_params(axis='y')
ax2.text(t[15], i[10], r'$i(t)$', fontsize=12)
plt.show()
# Naboj kot funkcija
# kreiranje časovnega niza od 0 do 30 s korakom 0.1
t = np.arange(0.0, 30.0, 0.1)
# Naboj kot funkcija
def Q(tau):
return 5*(1-np.exp(-t/tau))
tau=[10,5,1]
labela=['Q1','Q2','Q3']
# labela=['$Q_1(t)$','$Q_2(t)$','$Q_3(t)$'] # Odkomentiraj za lepši izpis
lstil=['-','--',':']
plt.figure()
# Zanka, ki se izvrši večkrat in iterira (povečuje) indeks i
for i in range(3):
plt.plot(t, Q(tau[i]),label=labela[i],ls=lstil[i],color='k')
plt.xlabel('čas (s)')
plt.ylabel('Naboj (mC)')
plt.title('Naboj v odvisnosti od časa')
plt.legend()
plt.show()