<jupyter_start><jupyter_text>Uvod u programsku okolinu `Jupyter Notebook` i programski jezik `Python 3.x` za računalnu elektromagnetsku kompatibilnost 1. `Jupyter Notebook` i `Jupyter Lab` okruženjeInteraktivna analiza digitalne obrade signala kao standardni dio računalne elektromagnetske kompatibilnosti u ovim vježbama bit će realizirana koristeći `jupyter lab` okolinu razvijenu od strane [Project Jupyter](https://jupyter.org/). `Project Jupyter` je *open source* projekt zasnovan na postojećem [IPython](https://ipython.org/) kernelu pri čemu je osnovna ideja Jupyter Lab programskog okruženja mogućnost interaktivne analize istovremeno koristeći podržani programski jezik (`Python`, `Julia` ili `R`) i tekst u *markdown* formatu. Osim toga, osigurana je i vizualna analiza podataka koristeći različite GUI alate već ugrađene u `jupyter`.Instalacija najnovije verzije `Pythona`, `jupyter` jezgre i svih potrebnih paketa je osigurana kroz `Anaconda Team Edition` instalacijski paket (detaljna upustva za instalaciju na linku [ovdje](https://www.anaconda.com/products/individual)). Za slučaj da `Anacondu` koristite u Windows okruženju, pokretanje `jupyter` jezgre se ostvaruje kroz `Anaconda prompt` terminal koji osigurava da je kompletna kofiguracija okruženja pravilno postavljena. Kroz ove laboratorijske vježbe, potrebno je koristiti osnovne funkcionalnosti sljedećih `Python` paketa:- `scipy` - implementacija čestih znanstvenih i statističkih računalnih paradigmi i tehnika. Ovaj paket ćemo posebno koncentrirano promatrati kroz module `scipy.fft` i `scipy.signal`;- `numpy` - numerički `Python` paket za olakšanu manipulaciju nizovima i matricama. Ovaj paket prozilazi iz jezgre `scipy` paketa;- `matplotlib` - paket za vizualizaciju raličitih tipova podataka.Jednom kad je `Anaconda` i svi potrebni paketi instalirani na računalo, pokretanje `jupyter` servera i `lab` klijenta u internetskom pregledniku se ostvaruje ili kroz `Anaconda prompt` terminal (Windows) ili kroz standardni terminal (većina Linux distribucija) sljedećom naredbom:```$ jupyter lab```Na ovaj način pokrećemo server i automatski otvaramo `jupyter lab` sučelje u zadanom internetskom pregledniku.Kao prvi korak potrebno je testirati pravilan rad `lab` sučelja pokretanjem sljeće ćelije naredbom `shift` + `enter`.<jupyter_code>x = 2 * 21
print(x)<jupyter_output><empty_output><jupyter_text>Svaka se **bilježnica** (datoteka s nastavkom .ipynb unutar koje se trenutno nalazimo) sastoji od više ulaznih i izlaznih ćelija, gdje ulaz sadrži kôd koji se izvršava, dok pripadna izlazna ćelija prikazuje rezultat izračuna. Važno je napomenuti da ove ćelije podržava kod na jezicima: **Ju**lia, **Pyt**hon ili **R** (imajte na umu ime: **jupyter**), kao i tekst u *markdown* formatu, u HTML-u te u $\LaTeX$ formatu. Kao takve, bilježnice su izvrstan alat za sastavljanje interaktivnih izračunljivih dokumenata koji se mogu izravno izvesti u HTML ili $\LaTeX$ / PDF izvješća. Novu ulaznu ćeliju se može kreirati ispod položaja kursora ili klikom na gumb `+` u gornjem lijevom izborniku ili pritiskom slova `b` na tipkovnici. Ako uređujete ćeliju, možete pritisnuti `Esc` za ulazak u naredbeni način u kojem možete dodavati, manipulirati ili brisati ćeliju. Da biste izbrisali ćeliju, dvaput pritisnite `d` u naredbenom načinu. Da biste promijenili vrstu ćelije iz koda u *markdown*, pritisnite `m` u naredbenom načinu. Pritisnite `y` da biste ga vratili na kôd. `Python` kôd izvršava temeljna python jezgra, čiji je trenutni status prikazan u gornjem desnom krugu prozora bilježnice. Neispunjeni krug označava da je jezgra trenutno neaktivna. Ako je umjesto kruga prikazan pješčani sat, jezgra je zauzeta računanjem. Ovu pojavu možete promotriti izvršenjem sljedeću ćelije:<jupyter_code>summ = 0
for i in range(50000000):
    summ += 1
print(summ)<jupyter_output><empty_output><jupyter_text>Važno je napomenuti da je python jezgra jedan interpretirani proces koji sekvencijalno pokreće kôd u ćelijama koje se izvršavaju. To podrazumijeva da redoslijed vašeg izvršavanja određuje trenutno stanje jezgre, tj. koje varijable postoje i koje su vrijednosti tih varijabli. Konkretno, stanje se održava u više ćelija, kao što možete vidjeti u sljedećem primjeru:<jupyter_code>x = 42
print(x)
x = 24<jupyter_output><empty_output><jupyter_text>Ako izvršite dvije ćelije obrnutim redoslijedom, generirali biste pogrešku. To se u početku čini trivijalno, ali za složene bilježnice u kojima izvršavate stanice naprijed-natrag može postati prilično teško razumjeti kakvo je trenutno stanje. Uvijek možete izbrisati trenutno stanje zaustavljam trenutne jezgre.  2. `Python` Učitavanje paketa i pripadnih modula naredbom `import` iza koje slijedi ime paketa, nakon čega opcionalno možemo dodati i naredbu `as` iza koje slijedi alias:<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>`Python` je takozvani *dynamic-typed* programski jezik koji ne zahtjeva specificiranje tipova varijabli prikom inicijalizacije.<jupyter_code>x = 42
print(type(x))<jupyter_output><empty_output><jupyter_text>Eksplicitna konverzija tipova već inicijalizirane varijable je moguća na sljedeći način:<jupyter_code>x = float(x)
print(type(x))
x = '42'
x = int(x)
print(type(x))
x
a = '42'
b = int(a)
print(type(b))<jupyter_output><empty_output><jupyter_text>Kao što se moglo vidjeti iz prethodna dva primjera, `Python` automatski, tijekom interpretacije koda, varijabli pridjeljuje tip s obzirom na pohranjenu vrijednost. Ako broj $42$ želimo odmah pohraniti kao `float`, to možemo učiniti na sljedeći način:<jupyter_code>x = 42.
print(type(x))<jupyter_output><empty_output><jupyter_text>`Python` podržava i rad sa stringovima:<jupyter_code>s1 = 'some text'
s2 = 'additional text with "quote"'
print(s1)
print(s2)
s3 = """This is a very long string 
that spans
multiple
lines
"""
print(s3)<jupyter_output><empty_output><jupyter_text>Učestalo ćemo se susretati i sa logičkim tipovima:<jupyter_code>a = True
b = False
if a:
    print(b)
a is True
a = [1, 2]
b = [1, 2]

a is b
id(a)
id(b)
a == True
a == True
a * b
a = True
b = False
(a | b) is (a + b)
a & b
a | b<jupyter_output><empty_output><jupyter_text>Funkcije u `Pythonu` se definiraju koristeći `def` ključnu riječ nakon koje slijedi ime funkcije i opcionalni parametri. Funkcija može i ne mora vraćati jednu ili više vrijednosti:<jupyter_code>def some_function(x, y=42, z='poruka'):
    """docstring - opis funkcije"""
    print("Parameter x =", x)
    print("Parameter y =", y)
    print("Parameter z =", z)
    return x + y
some_function(1, 2, 3)
help(some_function)<jupyter_output><empty_output><jupyter_text>Prilikom definicije funkcije, i općenito prilikom pisanja koda, moramo imati na umu da je parser osjetljiv na razmake i tabove:<jupyter_code>def additional_function(x, y):
    print(x)
    sum = x + y
    return sum<jupyter_output><empty_output><jupyter_text>Petlje i kondicionali:<jupyter_code>for x in range(1, 17):
    print('x =', x)
type(range(1, 16))
list(range(1, 16))
x = 1
while x <= 15:
    print("x =", x)   
    x = x+1
x = 3
y = 5
if x < y:
    print("x is smaller than y")
elif x > y:
    print("x is larger than y")
else: 
    print("x and y are equal")<jupyter_output><empty_output><jupyter_text>Osnovni podatkovni tip s kojim ćemo se često susretati je lista:<jupyter_code>signal = [2.0, 3.0, 1.0, 0.0, 2.0, 4.0]
print(signal)<jupyter_output><empty_output><jupyter_text>Za razliku od Matlab sintakse, Python sintaksa indeksiranje podatkovnih tipova s više vrijednosti započinje od $0$. ostala pravila indeksiranja su više, manje slična:<jupyter_code>print(signal[0:3])
sig2 = signal[:-2:]
sig2
print(signal[::2])<jupyter_output><empty_output><jupyter_text>Vrlo važan koncept su i *list comprehensions*. Npr:$f[n] = 2n^3 + 3n - 4$ pri čemu je $n \in [0, 10]$u `Pythonu` bi moglo biti dobiveno na sljedeći način:<jupyter_code>f_n = [2*n**3 + 3*n - 4 for n in range(0, 10)]
print(f_n)<jupyter_output><empty_output><jupyter_text>2. `NumPy` -  osnove<jupyter_code>import numpy as np
signal = [0, 1, 2, 3]
import matplotlib.pyplot as plt 

plt.plot(signal)
signal * 2
amp_signal = [sig*2 for sig in signal]
amp_signal
amp_signal = []
for sig in signal:
    amp_signal.append(sig * 2)
amp_signal
plt.plot(signal)
plt.plot(amp_signal)
noise = [0.1, -0.21, -0.03, 0.11]
signal + noise<jupyter_output><empty_output><jupyter_text>`NumPy` niz je bitno različit od liste u smislu da predstavlja matematički vektor na kojem možemo izvoditi aritmetičke operacije.Da bismo koristili `NumPy` nizove, prvo moramo definirati korištenje paketa a onda nizove izravno inicijaliziramo koristeći postojeće liste:<jupyter_code>signal
import numpy as np

signal_arr = np.array(signal)
noise_arr = np.array(noise)
signal_arr
type(signal_arr)
print(signal_arr)
signal_arr.ndim
noisy_signal_arr = signal_arr + noise_arr
print(noisy_signal_arr)
plt.plot(signal_arr*2)
amp_signal_arr = signal_arr * 2
print(amp_signal_arr)<jupyter_output><empty_output><jupyter_text>Niz predstavlja jednodimenzionalni vektor čiji broj dimenzija odgovara broju elemenata proslijeđene liste. Za promjenu strukture ili dimenzionalnosti numpy niza možemo koristiti metodu `reshape`.<jupyter_code>signal_arr.ndim
signal_arr.shape
signal_arr
signal_arr.reshape(1, 4)
signal_arr.reshape(-1, 1)
signal_arr.reshape(2, 2)<jupyter_output><empty_output><jupyter_text>Slijedeća inicijalizacija generira $3 \times 3 \times 3$ tenzor, koji možemo zamisliti kao kocku koja se sastoji od tri sloja dvodimenzionalnih matrica.<jupyter_code>tensor = np.array([[[0,1,0],[1,0,1],[1,1,1]], [[0,0,0],[1,0,1],[1,1,0]], [[1,0,0],[0,0,0],[1,1,1]]])
print('tensor values: \n\n', tensor, end='\n\n')
print('tensor shape: ', tensor.shape)<jupyter_output><empty_output><jupyter_text>Sva pravila indeksiranja koja vrijede za liste, vrijede i za `NumPy` nizove, osim sto nam `NumPy` omogućava prelazak u 3 ili više dimenzija.<jupyter_code>tensor[1, 1, :]
tensor[2, :, 0]
tensor[-1, -1, -2:-1]
(tensor[2, :, :] == tensor[2]).all()<jupyter_output><empty_output><jupyter_text>2. `Matplotlib` -  osnove<jupyter_code>import numpy as np

X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C = np.cos(X)
S = np.sin(X)<jupyter_output><empty_output><jupyter_text>`X` je predstavljen kao `NumPy` niz s 256 vrijednosti u rasponu od $-\pi$ do iuključeno $+\pi$. `C` je kosinus (256 vrijednosti), a S je sinus (256 vrijednosti) od `X`.<jupyter_code>import matplotlib.pyplot as plt

plt.plot(X, C)
plt.plot(X, S)<jupyter_output><empty_output><jupyter_text>`Matplotlib` dolazi sa skupom zadanih postavki koje omogućuju prilagodbu raznih svojstava. U `matplotlibu` možete kontrolirati zadane postavke: veličine slike i DPI, širinu linije, boju i stil, osi, svojstva osi i mreže, svojstva teksta i fonta itd. Iako su zadane postavke `matplotliba` u većini slučajeva prilično dobre, možda ćete htjeti izmijeniti neka svojstva za određene slučajeve (pogotovo kada je riječ u izvještajima, znanstvenim člancima ili modernim web orjentiranim preglednicima vizualizacija).<jupyter_code>plt.figure(figsize=(9, 6), dpi=80)
plt.plot(X, C, color='blue', linewidth=2.5, linestyle='-', label='cos(x)')
plt.plot(X, S, color='red',  linewidth=2.5, linestyle='-', label='sin(x)')

t = 2*np.pi/4
plt.plot([t,t],[0,np.cos(t)], color ='blue', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.cos(t),], 50, color ='blue')

plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
             xy=(t, np.sin(t)), xycoords='data',
             xytext=(+45, -30), textcoords='offset points', fontsize=16,
             arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))

plt.plot([t,t],[0,np.sin(t)], color ='red', linewidth=1.5, linestyle="--")
plt.scatter([t,],[np.sin(t),], 50, color ='red')

plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$',
             xy=(t, np.cos(t)), xycoords='data',
             xytext=(-90, -50), textcoords='offset points', fontsize=16,
             arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))

plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
       [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
plt.yticks([-1, 0, +1],
       [r'$-1$', r'$0$', r'$+1$'])
plt.grid()
plt.legend(loc='upper left', frameon=False)
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1149331594391914, 'fraction_numerical': 0.018747962178024127, 'mean_word_length': 5.774710104914412, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 96, 'https://': 3, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '333596', 'license': 'MIT', 'n_tokens_mistral': 5341, 'n_tokens_neox': 5163, 'n_words': 1341, 'path': 'emc_512/lab/Python/01-lab-ex.ipynb', 'repo_name': 'antelk/teaching', 'size': '12268'}