Praktikum 15¶

Allolevad ülesanded on kusrsuse "Sissejuhatus programmeerimisse Pythoni baasil" YFX0500 praktikumis koos kursusega ja kodus iseseisvalt lahendamiseks. Kuidas lahendada allolevaid ülesandeid? Uuri ja kasuta loengus kommenteeritud süntaksi näiteid, abiinfot (Pythoni sisseehitatud funktsioon help, jne.), Internetti ja enda aju. Küsimuste korral, mis tekivad praktikumi ajal, pöördu õppejõu või õppejõudude poole. Iganädalaselt peale praktikumi toimumist avaldatakse ülesannete lahendused kursuse kodulehel.

Viimati uuendatud 8.12.2024.

Ülesanne 1:

Kirjuta Pythoni klass mis loob etteantud ühe muutujaga funktsiooni $f(x)$ diskretiseeritud väärtustega objekte etteantud vahemikus $x \in [x_{\rm start}, x_{\rm stopp}]$. Lisaks funktsiooni $f(x)$ väärtusetele peab programm leidma ka selle esimese $f'(x)$ ja teise $f''(x)$ täistuletise disktretiseeritud väärtused. Lisa klassile neli meetodit. Meetodid peavad looma/väljastama/kuvama graafikuid:

  1. funktsioonist $f(x)$ etteantud vahemikus,
  2. selle esimesest tuletisest $f'(x)$,
  3. selle teisest tuletisest $f''(x)$ ja
  4. kuvama kõiki eelmainituid funktsioonide graafikuid samal teljepaaril.

Ülesanne 2:

Kontrolli kas võrdus kujul: $$\ln(1 + 2 + 3) = \ln(1) + \ln(2) + \ln(3)$$ on tõene. Keskkooli ajast teame, et $$\ln(1 \cdot 2 \cdot 3) = \ln(1) + \ln(2) + \ln(3)$$ on tõene. Kuidas seletada esimest võrdust?

Ülesanne 3:

Loo allolev numpy.ndarray andmemassiiv. Tee sellest massiivist koopia milles on kõik kolmega mittejaguvad arvud asendadtud metsalise arvuga $666$ (Viide: Piibel Ilmutuse raamat 13:18) või $616$ kui tahad olla ajalooliselt ja faktiliselt täpne, vt. https://en.wikipedia.org/wiki/Number_of_the_beast

Massiiv:

[[30 29 28 27 26]
 [25 24 23 22 21]
 [20 19 18 17 16]
 [15 14 13 12 11]
 [10  9  8  7  6]
 [ 5  4  3  2  1]]

Oodatav tulemus:

[[ 30 666 666  27 666]
 [666  24 666 666  21]
 [666 666  18 666 666]
 [ 15 666 666  12 666]
 [666   9 666 666   6]
 [666 666   3 666 666]]

Oodatav tulemus juhul kui Sa oled ajaloolane või Sa ei hooli pikaajalisest kristlikust traditsioonist mille kohaselt tuleb uskumist eelistada teadmisele:

[[ 30 616 616  27 616]
 [616  24 616 616  21]
 [616 616  18 616 616]
 [ 15 616 616  12 616]
 [616   9 616 616   6]
 [616 616   3 616 616]]

Ülesanne 4:

Loo allolev numpy.ndarray andmemassiiv. Leia selles esinevate paarisarvude summa.

Massiiv:

[[30 29 28 27 26]
 [25 24 23 22 21]
 [20 19 18 17 16]
 [15 14 13 12 11]
 [10  9  8  7  6]
 [ 5  4  3  2  1]]

Vastus: 240

Ülesanne 5:

Loo graafik mis kujutab Lissajous kõverat. Kõver on esitatud parameetrilisel kujul: $$ \begin{cases} x(t) = A \sin (a t + \delta),\\ y(t) = B \sin (b t), \end{cases} $$ kus parameeter $t \in [0, t_\text{max})$ on $x$-i ja $y$-t siduv muutuja, ning $A$, $B$, $a$, $b$ ja $\delta$ on meelevaldselt valitavad konstandid. Tulemus sõltub tugevalt $a$ ja $b$ suhtest.
Lisainfo: https://en.wikipedia.org/wiki/Lissajous_curve

Ülesanne 6:

Kasutades Ülesandes 5 defineeritud Lissajous kõvera parameetrilist kuju, loo allpool kujutatud joonis.

Telgede eemaldamine:

import numpy as np

fig, axes = plt.subplots(2, 2)
axes[1, 1].remove()  # Telgede eemaldamine kohalt axes[1, 1].
No description has been provided for this image
Joonis 1. Ülesande 6 oodatav tulemus.

Ülesanne 7:

Leia kolmefaasilise voolu faaside hetkeliste pingete summa. Loo graafik mis kujutab iga faasi pinge väärtuse muutumist ajas koos kõigi faaside summa graafikuga. Normeeri pinge aegrida, st. vali pinge amplituudiks $|\max U(t)| = 1$. Loeme iga faasi vahelduvvoolu sageduseks $f = 50$ Hz.

Vihje: Loe Vikipeedia artiklit: https://en.wikipedia.org/wiki/Three-phase_electric_power

Ülesanne 8:

Loo Joonisel 2 kujutatud joonis (ligikaudselt, ei peal olema 1000% koopia). Ringi loomiseks kasuta allpool esitatud ringjoone parameetrilist kuju. Suu loomiseks kasuta parabooli. Silmade kujutamiseks kasuta punkte.

import numpy as np

theta = np.linspace(0, 2*np.pi, 100)
r = 1.9   # Raadius, vali ise.

x = r * np.cos(theta)
y = r * np.sin(theta)

No description has been provided for this image
Joonis 2. Ülesande 8 oodatav tulemus.

Ülesanne 9:

Kontrolli kas juhuslike arvude generaator numpy.random.rand loob arve mille jaotus on konstantne nagu väidab selle dokumentatsioon. Loo histogramm kasuta vähemalt 30 000 juhuslikku arvu. Loo histogramm kasutades:

  1. Matplotlib graafikutüüpi matplotlib.pyplot.hist.
  2. NumPy funktsiooni numpy.histogram koos Matplotlib graafikutüüpi matplotlib.pyplot.plot (tavaline graafik).

Joonised 3 ja 4 kujutavad oodatavaid tulemusi.

No description has been provided for this image
Joonis 3. Ülesande 9.1 oodatav tulemus. Histogramm arvutati kasutades 30 000 arvu. Histogrammi loomiseks on kasutatud teegi Matplotlib graafikutüüpi matplotlib.pyplot.hist (vaikimisi seaded).
No description has been provided for this image
Joonis 4. Ülesande 9.2 oodatav tulemus. Histogramm arvutati kasutades 30 000 arvu. Histogrammi andmete leidmiseks on kasutatud funktsiooni numpy.histogram.

Ülesanne 10:

Kontrollime kahe integraatori täpsust. Kasuta integraatoreid:

  1. scipy.integrate.cumulative_trapezoid
  2. scipy.integrate.cumulative_simpson

Kirjuta programm mis teostab funktsiooni kumulatiivse integreerimise ja seejärel tuletise (numpy.gradient) võtmise etteantud arvu n korda. Defineeri lõigul $x \in [-1, 1]$ funktsioon kujul: $$ f_0(x) = {\rm e}^{- \alpha x^2} \equiv \exp(- \alpha x^2), $$ kus parameeter $\alpha$ on kellukakujulise pulsi laiust määrav parameeter.

Eelmainitud tsükli jooksul leitakse numbriliselt integraal kujul: $$ F(x) = \int \!\! f(x)\, {\rm d}x, $$ ning seejärel leitakse kohe ka tuleti ehk teostatakse pöördtehe kujul: $$ f(x) = \frac{{\rm d}}{{\rm d} x}F(x). $$ Esimese tsükli ajal asendatakse $f(x) = f_0(x)$.

Loo mõlema integraatori jaoks kolm graafikut mis on sarnased Joonisel 5 kujutatud graafikutega. Viimasel graafikul leitud maksimaalsed erinevused on leitud järgmiselt: $$ \text{tulemus}_i = \max(|f_i(x) - f_0(x)|) = |\max(f_i(x) - f_0(x))|, $$ kus $i$ on eelmainitud tsükkel.

No description has been provided for this image
Joonis 5. Ülesande 10 üks oodatavatest tulemustest. Kujutatud graafikute ja joonise loomiseks kasutati integraatorit scipy.integrate.cumulative_simpson ning $n = 30$ integreerimise ja tuletise võtmise tsüklit. Algse pulsi $f_0(x)$ defineerimiseks kasutati $\alpha = 20$ ning $50$ andmepunkti.

Ülesanne 11:

Kontrollime kas seos Kuu kraatrite diameetri ja vanuse vahel on astmeseadus. Lae kursuse kodulehelt alla fail Kuu.csv käsitsi või kasuta Pythoni standardteegi moodulit urllib. Faili saab enda töökausta alla laadida näiteks järgmise koodiga:

from urllib.request import urlretrieve
from pathlib import Path

def save_fail_kursuse_kodulehelt(fname):
    my_file_obj = Path(fname)
    if my_file_obj.is_file():
        print("Fail on juba töökaustas...")
    else:
        url = f"https://www.tud.ttu.ee/web/dmitri.kartofelev/YFX0500/{fname}"
        urlretrieve(url, fname)
        print("Fail alla laetud töökausta...")

server_file_name = "Kuu.csv"
save_fail_kursuse_kodulehelt(server_file_name)

Allalaetud fail sisaldab muuseas Kuu kraatrite diameetreid ja nende vanust, vt. kaks viimast veergu. Sorteeri andmed kraatrite vanuse järgi kasutades koodi:

import numpy as np

data = np.loadtxt('Kuu.csv',
                  delimiter=',',
                  skiprows=1,
                  unpack=False,
                  usecols=(-2, -1))  # Viimased veerud.

data_sorted = data[data[:, 1].argsort()]  # Sorteerimine.

vanus = data_sorted[:, 1]  # Kraatrite vanused.
d = data_sorted[:, 0]  # Kraatrite diameetrid.

Kustuta või eemalda andmedread kus on kraatri diameeterid suuremad kui 45 km. Loo graafikud, kasutades eelnevalt sorteeritud andmeid, kus kuvatakse kraatrite diameetri seost nende vanusest ja andmemassiivi indeksist, vt. Joonis 6. Loo histogramm. Veendu, et Kuu kraatrite jaotus on log-log tüüpi graafikul ligikaudu sirge, vt. Joonis 6.

No description has been provided for this image
Joonis 6. Ülesande 11 oodatav tulemus. Histogrammi loomisel kasutati 10 vahemikku (bins) ja logaritmilisi telgi.

Ülesanne 12:

Leia päratu integraali väärtus kasutades funktsiooni scipy.integrate.quad, $$ \int\limits_{-\infty}^{\infty} \! {\rm e}^{- x^{2}}\, {\rm d}x ~ \equiv \!\!\! \int\limits_{-\infty}^{\infty} \! \exp(-x^2)\, {\rm d}x. $$ Kontrolli leitud tulemuse õigsust.

Analüütiline vastus: $$ \int\limits_{-\infty}^{\infty}\! {\rm e}^{- x^{2}}\, {\rm d}x ~ \equiv \!\!\! \int\limits_{-\infty}^{\infty} \! \exp(-x^2)\, {\rm d}x = \sqrt{\pi}. $$

Ülesanne 13:

Leia polünoomi globaalse miinimumi argumendi väärtus kui: $$ f(x) = 5 x^6 - 3 x^5 + 23 x^3 + (x + 1)^2 . $$ Loo joonis mis kujutab polünoomi graafikut, juhul $x \in [-4, 4]$.

Ülesanne 14:

Leia kõvera ja sirge lõikepunktid. Sirge ja kõver on antud järgmisel kujul: $$ y_1(x) = -0.1 x, $$ $$ y_2(x) = \sin x. $$ Otsi lõikepunkte vahemikus $x \in [-6, 6]$. Kujuta leitud punktid koos sirge $y_1$ ja kõveraga $y_2$ ühisel teljepaaril. Joonis 7 kujutab ülesande lahendit.

Vihje: Loeng 15 näide.

No description has been provided for this image
Joonis 7. Ülesande 14 oodatav tulemus. Lõikepunktid on kujutatud punaste punktidega.

Ülesanne 15:

Konvolutsiooni kasutatakse piltidelt huvipakkuvate kujutiste tuvastamiseks ja lokaliseerimiseks. Analüüsitav pilt konvoleeritakse tavaliselt palju väiksema pildiga mida hakkame nimetama tuumaks. Tuum sisaldab kujutist mida soovime suuremalt pildilt leida. Konvolutsiooni teel loodud pildi globaalne maksimum peaks vastama otsitava kujutise asukohale. Vaatame kas selline lähenemine töötab:

  1. Lae kursuse kodulehelt alla failid fig_L15.tiff ja ker_L15.tiff.
  2. Loe sisse piltide andmed. Eralda pildi andmetest üks kolmest värvikanalist (fail sisaldab kanaleid: Red, Green, Blue, alpha). Kasuta andmete lugemiseks meetodit matplotlib.image.imread:
from matplotlib.image import imread
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import convolve

img = imread('fig_L15.tiff').astype(np.float32)
ker = imread('ker_L15.tiff').astype(np.float32)
  1. Teosta konvolutsiooni operatsioon kasutades funktsiooni scipy.signal.convolve (konvolutsioon = pilt $\ast$ tuum). Teosta konvolutsiooni kahe massiivi vahel: 1) failist fig_L15.tiff eraldatud andmemassiiv; 2) failist ker_L15.tiff eraldatud andmemassiivi.
  2. Leia konvolutsiooni tulemusel leitud massiivi maksimaalse värviintentsiivsusega piksel. Leia selle piksli asukoht massiivis.
  3. Loo joonis mis on sarnane Joonisele 8. Pildiandmete kuvamiseks kasuta meetodit matplotlib.pyplot.imshow. Kujuta pildifailidest eraldatud massiivid ja konvolutsiooni tulemusel saadud massiivi. Lisa viimasele teljepaarile ka eelnevalt leitud maksimaalse värviintentsiivsusega piksel asukoht, vt. Joonis 8.
No description has been provided for this image
Joonis 8. Ülesande 15 näidislahendus. Leitud maksimaalse värviintentsiivsusega piksel on kujutatud punase plussiga.

Ülesanne 16:

Loome eelmise ülesande konvolutsioonitehtes kasutatud andmemassiivid ja kuvame neid joonisel, vrd. Joonis 9.

Häguse servaga punkti või ringi kujutise saame luua kasutades näiteks funktsiooni kujul: $$ z = z(x, y) = {\rm e}^{-\alpha [(x - x_\text{s})^2 + (y - y_\text{s})^2 ]} \equiv \exp( -\alpha [(x - x_\text{s})^2 + (y - y_\text{s})^2 ]), $$ kus $\alpha$ on loodava häguse punkti suuruse parameeter, $x_\text{s}$ ja $y_\text{s}$ on häguse punkti asukoht graafiku keskpunkti $O = (x, y) = (0, 0)$ suhtes. Funktsiooni $z(x, y)$ väärtused saad siduda ristkoordinaatidega $x$ ja $y$ järgmiselt:

import matplotlib.pyplot as plt
import numpy as np

alpha = 0.2  # Suuruse parameeter.

x = np.linspace(-5, 5, 100)
y = np.linspace(-4, 4, 100)

xx, yy = np.meshgrid(x, y)  # Loome andmemassiivi kuju.
z = np.exp(-alpha*((xx - x_nihe)**2 + (yy - y_nihe)**2))  # Loome massiivi andmed.

data = (x, y, z)

Loodud andmed saad järgi vaadata kasutades näiteks matplotlib graafikutüüpi matplotlib.pyplot.contourf ja väljakutset kujul: matplotlib.pyplot.contourf(*data, levels=100).

Programmi töövoog:

  1. Loo kaks massiivi üks suurem ja teine väiksem (resolutsioon) sarnaselt Joonisel 9 kujutatud massiividega. Sisuliselt loo originaalne anlüüsitav pilt ja tuum sarnaselt eelmisele ülesandele.
  2. Teosta konvulutsioon ning leia häguse servaga punkti asukoht sarnaselt eelmises ülesandes tehtule.
  3. Loo joonis mis on sarnane Joonisega 9. Lisa konvolutsiooni graafikutele häguse servaga punkti asukoht kasutades meelevaldselt valitud markerit.
No description has been provided for this image
Joonis 9. Ülesande 16 oodatav tulemus. Loodud andmemassiivid on kujutatud kasutades Matplotlib graafikutüüpe matplotlib.pyplot.contourf ja matplotlib.pyplot.contour (alumise rea parempoolne teljepaar). Häguse servaga punkti asukoht on kujutatud punase plussiga.

Ülesanne 17:

Kirjuta programm mis loob 8-bitiseid ühe värvikanaliga ehk must-valgeid .tiff failivormingus pilte. Kasuta eelmises ülesandes loodud andmemassiivi defineeriv kood.

Loo kolm funktsiooni:

  1. Funktsioon mis loob andmemassiivi (vt. eelmine ülesanne).
  2. Funktsioon mis kuvab graafiliselt loodud massiivi. Kasuta Matplotlib graafikutüüpi matplotlib.pyploy.imshow. Joonis 10 kujutab ühte loodud massiivi.
  3. Funktsioon mis salvestab töökausta kaks 8-bitist pildifaili $-$ originaali ja selle negatiivi. Kasuta pythoni funktsiooni kujul:
def save_8bit_image(fname, dat):
    '''Salvestab kaks pilti töökausta.
    fname: str
        Loodavate failide failinimede tüvi.
    dat: numpy.ndarray
        2D massiiv mis sisaldab pildi andmeid.
    '''
    # Normeerime vahemikku [0,256]. Andmetüüp np.uint8 (unsigned 8-bit integer).
    img8bit = (((dat - dat.min()) / (dat.max() - dat.min()))*255.9).astype(np.uint8)
    # Salvestamine:
    # Õige värv: 0=must ja 256=max intensiivsus, valge.
    imsave(f'{fname}.tiff', img8bit, cmap='gray')
    # Negatiiv.
    imsave(f'{fname}_neg.tiff', img8bit, cmap='Grays')
    return True

Joonis 11 kujutab funktsiooniga save_8bit_image loodud pilte mis vastavad Joonisel 10 kujutatud andmemassiivile.

No description has been provided for this image
Joonis 10. Ülesande 17 loodud andmemassiiv milles on $i = 300$ rida ja $j = 450$ veergu täisarve. Häguse servaga punkti asukohaks on valitud alumine vasakpoolne serva lähedane piirkond. Andmedmassiiv on kujutatud kasutades Matplotlib graafikutüüpi matplotlib.pyplot.imshow.
No description has been provided for this image   No description has been provided for this image
Joonis 11. Ülesande 17 oodatav näidistulemus. Loodud 8-bitised .tiff failivormingus pildid: originaal ja selle negatiiv. (NB! Enamus veebilehitsejaid ei toeta .tiff pildifaile. Siia pesastatud piltide tegelik failiforming on .png.)

Ülesanne 18:

Kasutades parabooli võrrandit kujul: $$ f(x) = x^2. $$ Loo $n = 10$ andmepunkti mis asuvad paraboolil. Lisa loodud punktidele valge müra omades väärtusi vahemikus $[-1, 1]$ allpool näidatud viisil. Lähenda loodud andmetele teist järku polünoom kasutades teeki NumPy.

Müra lisamine:

import numpy as np
import matplotlib.pyplot as plt

n = 10  # Andmepunktide arv graafikul.

x = np.linspace(-2, 2, n)

y_orig = x ** 2  # Parabool.
y = y_orig + 2 * np.random.rand(n) - 1  # Valge müra lisamine.

Joonis 12 kujutab võimalikku näidislahendit.

Vihje: Vt. loengu näiteid.

No description has been provided for this image
Joonis 12. Ülesande 18 oodatav tulemus.

Kodus¶

Ülesanne 19:

Loo joonis kasutades Gumowski-Mira kujutuse (fraktaali) definitsiooni. Kujuta iga iteratsiooni tulemus pikslina $xy$-tasandile. Gumowski-Mira fraktaal on esitatud kujutusega kujul: $$ \begin{cases} x_{n+1} = b y_n + F(x_n),\\ y_{n+1} = -x_n + F(x_{n+1}), \end{cases} $$ kus $n$ on iteratsiooni samm ja kus $$ F(x) = a x + \frac{2 (1 - a) x^2}{1 + x^2}, $$ ning kus $a$ ja $b$ on parameetrid (vali väärtused ise). Joonis 13 kujutab ülesande lahendit.

No description has been provided for this image
Joonis 13. Ülesande 19 oodatav tulemus. Kujutatud kujutis on genereetitud kasutades $n = 10^5$ iteratsiooni.

Ülesanne 20:*

Loo joonis kasutades Gumowski-Mira fraktaali definitsiooni. Kujuta iga iteratsiooni tulemus punktina $xy$-tasandile. Kasuta graafikutüüpi matplotlib.pyplot.scatter. Värvi fraktaali iga punkt (iteratsioon) vastavalt selle kaugusele punktist $O = (x, y) = (0, 0)$. Kauguse $k$ leidmiseks kasuta valemit kujul: $$ k(x, y) = \sqrt{x^2 + y^2}. $$ Gumowski-Mira fraktaal on esitatud kujutusega kujul: $$ \begin{cases} x_{n+1} = b y_n + F(x_n),\\ y_{n+1} = -x_n + F(x_{n+1}), \end{cases} $$ kus $n$ on iteratsiooni samm ja kus omakorda: $$ F(x) = a x + \frac{2 (1 - a) x^2}{1 + x^2}, $$ ning kus $a$ ja $b$ on parameetrid (vali väärtused ise). Joonis 14 kujutab ülesande lahendit.

No description has been provided for this image
Joonis 14. Ülesande 20 oodatav tulemus. Kujutatud kujutis on genereetitud kasutades $n = 10^5$ iteratsiooni. Kasutatud Matplotlib värvipaletti nimi on 'twilight'.

















☻   ☻   ☻