Piccola guida a Matlab/Octave
Piccola guida a Octave/Matlab
Questa vuole essere una piccola guida incompleta e non esaustiva di introduzione all'uso di Octave/Matlab ed è rivolta agli studenti di TDS 2008, in quanto cercadi spiegare solamente ciò che è stato affrontato durante il primo semestre di TAENSM, con espliciti riferimenti a quanto fatto in classe, oltre a dei suggerimenti(rivolti soprattutto a chi "lavora" con windows XP) su come lavorare più comodamente, piacevolmente e produttivamente.
A titolo di esempio, lacunosa è la descrizione della funzione plot(si rimanda all'help della medesima per approfondimenti), non vengono inoltre introdotte le matrici, non viene dato nessun fondamento teorico del linguaggio, e molte sono le non rigorosità(ad esempio nel numero di argomenti di una funzione) ecc.
Non troverete qui procedimenti logici per raggiungere la soluzione dei problemi che ci vengono posti(spero che riusciremo a pubblicarli altrove),ma troverete solamente i mezzi necessari per implementarli in Octave.
Si farà spesso riferimento a Matlab e Octave utilizzando i due nomi come sinonimi. La differenza tra i due la trovate nelle FAQ di tecnosuono.org .
Ho scritto tutto ciò di corsa in due giorni, quindi sarà pieno di errori, vi prego di segnalarmeli.
Per insulti, repliche, suggerimenti, correzioni, donazioni ecc potete contattarmi all'indirizzo email che ha come dominio "yahoo.it" e come username "giuliomoro".
Vorrei innanzitutto far chiarezza su ciò che matlab/octave è effettivamente(per quanto ci riguarda): è un programma che fa calcoli e permette di visualizzarnenumericamente o graficamente, oppure esportarne, i risultati. Per fare ciò esso interpreta i comandi che vengono scritti sulla sua finestra di terminale. In questo modo può essere utilizzato come una calcolatrice. Ad esempio se volete conoscere il risultato dell'operazione 2+6 basta scrivere al prompt
che da come risultato
Similmente gli si può far fare calcoli più complessi come
che da ovviamente come risultato
Questi risultati possono essere assegnati a delle variabili, nel caso vogliano essere utilizzati successivamente:
che produce:
Matlab opera agevolmente con i vettori(array). Con vettore intendiamo un insieme ordinato di numeri, come ad esempio: 1 2 4 7 10 .
Per creare un array in Matlab si può, ad esempio, elencarne i valori, che devono essere racchiusi fra parentesi quadre:
produrrà:
1 2 4 7 10
Che è ovviamente inutile, in quanto non abbiamo assegnato questo array a nessuna variabile. Molto più utile è quanto segue:
1 2 4 7 10
A volte si può avere bisogno di creare un array di cui non si abbia voglia di elencare tutti gli elementi. Per fortuna è possibile fare gli sfaticati nelcaso(particolare ma molto frequente)in cui si abbia bisogno di un insieme di numeri equidistanti fra loro, come ad esempio: 1 2 3 4 5 oppure 0.23 0.46 0.69 0.92 1.15
Dunque volendo creare un array "equispaziato" in Matlab è necessario indicare, tra le parentesi quadre, il valore di partenza, l'incremento(la distanza tra ciascunelemento e il successivo) e il valore finale, separati da due punti(:) :
0 0.1 0.2 0.3 0.4 0.5 0.6
è comprensibile che quando gli elementi dell'array iniziano a diventare molti comincerà a darci fastidio vedere ogni volta sullo schermo l'elenco di tutti i valori degli elementi del neonato array. Per evitare ciò si aggiunge alla fine del comando un ; (punto e virgola) :
che ci eviterà di passare il pomeriggio a visualizzare sullo schermo i 1001(!) elementi dell'array.
Il punto e virgola dunque evita che sullo schermo ci venga mostrato il risultato dell'elaborazione. Spesso, per il motivo appena citato, ci tornerà comodo far sì che le cose vadano così, quindi consiglio di metterlo sempre a fine riga, tranne nei casi in cui ci sia utile visualizzare il risultato(ad esempio durante il debugging).
È possibile visualizzare il valore di un certo elemento(il primo, il secondo...) di un array in questa maniera:
Si noti che il primo elemento di un array è l'elemento 1 e non l'elemento 0, come succede in altri linguaggi di programmazione.
Sì ma 'sti array a cosa mi servono?
Con Matlab è facile utilizzare gli array per effettuare la stessa operazione su un insieme di numeri. Ad esempio, volendo il risultato della moltiplicazione dei numeri1 3 5 7 per 3 si può fare così:
g = f*3
3 9 15 21
Notare che quando si fa un'operazione tra uno scalare e un array il risultato è un array contenente il medesimo numero di elementi dell'array di partenza.
Nel codice Matlab possono essere inseriti dei commenti anteponendovi il simbolo % (percento):
In Matlab esistono delle funzioni built-in(costruite-dentro) utili per la maggior parte degli scopi che possono interessarci.
Il modo corretto per richiamare una funzione è il seguente:
dove func è il nome della funzione e arg è l'argomento della funzione.Ad esempio volendo indicare il logaritmo naturale di 5 scrivereste abitualmente su un pezzo di carta:
log 5
in questo caso il nome della funzione è "log" e l'argomento è "5".
In Matlab questo si traduce in:
i = log(5);
Il numero degli argomenti non è uguale per tutte le funzioni: si va da 0 a qualcuno.
E come faccio a sapere quanti sono e in che ordine devo scriverli?
Matlab include un utile ed esaustivo help in linea: è possibile consultare la documentazione relativa a ciascuna funzione built-in semplicemente scrivendo sul terminale:
help log
help log10
Spesso ci tornerà comodo utilizzare come argomenti di una funzione non dei valori numerici, ma il contenuto di qualche variabile precedentemente calcolata, oppureeseguire il calcolo direttamente negli argomenti della funzione:
k = 55;
l = j + k;
m = log10(l)
m = log10(j+k);
Questa è una lista incompleta di funzioni built-in in Matlab:
a volte i nomi sono self-explicative, altre volte danno solo un indizio di ciò di cui tratta la funzione, altre volte sono incomprensibili.Divertitevi a scoprirle...help aiuta.
Prestate particolare attenzione a : plot, length, sin
Il prof Nicola ha provato più volte a farci notare la stupidità dei nostri stupidi sistemi operativi monoutente, mouse-driven, stupid-programmed, crash-oriented etc etc...
Non entro nel merito della discussione, ma qui di seguito mostro come sia possibile lavorare con comodità anche con Windows XP.
Dopo un po' che scriviamo righe di codice dal prompt capiterà che nel bel mezzo dell'impegnativa risoluzione di un'importante problema facciamo partire un loop infinitooppure cancelliamo per sbaglio una variabile che avevamo calcolato con somma fatica o in qualche altra maniera crashamo Octave etc etc, con conseguente perdita di tuttoquanto abbiamo elaborato fino a quel punto
Potrebbe anche succedere che uno preferisca scrivere il codice da qualche parte in modo da avere chiaro tutto quanto mentre lavora e avere il codice pronto per eventuali modifiche senza doverlo ridigitare ogni volta...
Per fare ciò è possibile scrivere le righe di codice con un editor di testo PURO(that is, per voi(noi) Microsoftcentrici: NO Microsoft Word, NO Microsoft Wordpad, ma SÌ Microsoft Blocco note), e poi salvarle in un file con estensione .m .
Evviva! Abbiamo fregato il prof Nicola: esiste un programma Microsoft fornito col nostro sistema operativo stupido che ci permette di scrivere addirittura degli script in Matlab!
Sì certo, ma non lo fa nella maniera più comoda.
Consiglio dunque a chi è ancora stuck con il vecchio notepad di digitare il comando "edit" dal terminale di Octave. Ne uscirà un editor di teso fantastico, con le non indifferenti capacità di:
I file salvati col VOSTRO editor di testo preferito potranno poi essere aperti con un praticissimo tasto destro-apri con-octave, ammesso che funzioni, solo che alla fine dell'esecuzione dello script, Octave verrà chiuso e non sarà possibile visualizzare i dati elaborati, né interagire con essi da terminale.
Abbiamo sperimentato in classe più volte una situazione del genere e avevamo provveduto a ""risolverla"" inserendo la funzione pause() (questa funzione non richiede argomenti)alla fine del codice nel file .m . In questa maniera il grafico che i nostri script producevano rimaneva visibile fino alla pressione di un tasto(in effetti pause() blocca l'esecuzione del programma finché non viene premuto un tasto), salvo poi chiudersi insieme ad Octave nel momento in cui il tasto veniva premuto.Questo metodo ci permette sì di visualizzare a lungo il grafico, ma non di interagire con le variabili calcolate dal programma, per scopi ad esempio di debugging o di controlloo di "improvement on the fly" dello script.
È dunque molto più comodo, una volta lanciato Octave, utilizzare il comando "run" per lanciare il file .m da noi elaborato. Ma come si fa a dirgli dove si trova sto file?
Il vostro programma mousclickautoinstallante vi avrà lasciato sul desktop un pratico doppioclickcollegamento a Octave. Bene, lanciandolo da lì Octave considererà come cartella homela cartella che si trova in c:/programmi/octave/bin dunque se avete un file .m in quella cartella basterà un semplice
È vero però che è ben scomodo mettere i nostri propri file .m lì dentro, in una cartella distante dal desktop e già piena di file...si rischia di fare confusione. Il nostro sistemaoperativo stupido ci viene però in aiuto un'altra volta:
Fate click(aaargh) col tasto destro sul suddetto collegamento, scegliete proprietà, nella maschera che si apre digitate(oppure copia incolla, tutto rigorosamente col mouse)nel campo "DA" il percorso completo della cartella in cui bramate tenere i vostri elaborati. Io ad esempio tengo una cartella sul desktop , quindi nel mio caso il percorso è:"c:/documents and settings/giulio/desktop/scriptoctave".
Ora quando riaprirete Octave utilizzando questo collegamento egli riconscerà come home la directory che avete appena settato, quindi con un pratico
dal prompt di octave potrete aprire il file nomefile.m che si trova nella vostra pratica cartella sul desktop, o dove più vi aggrada.Inoltre, una volta terminata l'esecuzione del medesimo, potrete continuare a lavorare sulle variabili che sono state calcolate da Octave, oppure lanciare un altro script, senza bisogno di riavviare octave(che pure, almeno sul mio computer) non è immediato a partire.
Ho inoltre recentemente scoperto che è possibile incollare il testo nel prompt di octave, il che si rivela spesso utile e pratico. Per farlo non funzionano ctrl V , ctrl shift V,shift ins o qualunque altra combinazione vi venga in mente, in Windows XP si può fare(a quanto ne so io)solo nel seguente modo:cliccando col tasto destro sul pulsante della finestra di octave nella barra delle applicazioni, selezionando modifica e poi incolla.
È inoltre molto utile la caratteristica di Octave di ricordarsi i comandi inseriti dal terminale. Questo significa che se avete appena scritto "A=1*4-log(10)/(4-a+b^2)"e vi serve riscriverlo e/o modificarlo(e farlo rieseguire a Octave), potete premere la frecciainsu, e riappariranno così al prompt i comandi che avete inserito recentemente.Ancora più utile può essere scrivere le prime lettere del comando che state cercando e premere la freccia insu, in questo modo appariranno solo i comandi già digitati che iniziano con quelle lettere.
Vediamo ora nel dettaglio le funzioni che abbiamo usato in classe:
Il numero degli elementi contenuti in un array si chiama "lunghezza dell'array". Per conoscerlo è possibile usare la funzione "length(arg)", dove l'argomento "arg" èl'array di cui vogliamo conoscere la lunghezza:
dur=5;
T=[0:sinc:dur-sinc];
numerodicampioni=length(T)
La funzione sin(arg) restituisce il seno dell'argomento "arg", che è l'angolo espresso in radianti:
Esiste in matlab la variabile di sistema "pi" che vale PIgreco (3.141592653589793...), per cui:
%si nota che questo valore è molto prossimo a zero, come è giusto che sia
Volendo calcolare al tempo 0.04 secondi il valore di una funzione sinusoidale di ampiezza 1 e frequenza 237:
A=1;
t=0.04;
valore=A*sin(2*pi*frq*t)
Abbiamo visto più sopra che è possibile far eseguire con un solo comando la stessa operazione su più valori, facendola eseguire non su uno scalare, ma su un array:
o = sin(pi*n)
0 0.5 1 0.5 0
Vediamo a cosa ci può servire questo per i nostri scopi:
abbiamo più volte avuto necessità di calcolare il valore di una funzione sinusoidale con determinate frequenza e ampiezza in un certo intervallo di tempo, per poi poterla elaborare in qualche maniera(sovracampionare, sottocampionare, sottoquantizzare, puslwitmodulare etc etc)
La prima cosa da stabilire è la frequenza di campionamento. L'inverso di questa è poi il sample-increment, ovvero l'intervallo di tempo che intercorre tra un campionee il successivo. Conoscendo il sample-increment e la durata che vogliamo che abbia il nostro campione possiamo crearci un vettore contenente tutti gli "istanti" in cuivogliamo calcolare il valore della sinusoide. Una volta creato questo array possiamo agevolmente calcolare i valori come abbiamo appena visto, basta decidere la frequenzache deve avere la nostra sinusoide:
sinc=1/fc;
dur=5
T=[0:sinc:dur-sinc];
A=1;
frq=100
y=A*sin(2*pi*frq*T);
Per verificare che la nostra sinusoide è effettivamente una sinusoide possiamo rappresentare graficamente i dati ottenuti, utilizzando la funzione"plot(x,y)"."x" è il vettore che contiene i valori delle ascisse a cui corrispondono sulle ordinate i valori di "y".
In pratica verra plottato un grafico i cui punti avranno le coordinate:
P1 ( x(1), y(1) )
P2 ( x(2), y(2) )
P3 ( x(3), y(3) )
ecc
ecc
ecc
Ovviamente la lunghezza dei due array dovrà essere la medesima, sennò si verificherà un errore.
Ad esempio:
produrrà il seguente grafico:

A questo punto uno si spara in bocca oppure riflette sul fatto che 220500 campioni non possono venire rappresentati molto bene sui 1024 pixel del vs schermo.
A questo punto quindi zoomiamo nella presunta sinusoide con la funzione axis(arg). L'argomento "arg" dev'essere un vettore.I primi due elementi di questo array saranno rispettivamente l'inizio e la fine del range che vogliamo visualizzare sull'asse x. Se aggiungiamo altri due valori,questi saranno l'inizio e la fine del range che vogliamo visualizzare sull'asse y.

Qui possiamo vedere che effettivamente c'è una sinusoide, e che siccome vengono visualizzati 5 periodi in 50 millisecondi, essa avrà un periodo di 10ms, ovvero unafrequenza di 100Hz.
È possibile decidere il colore e lo stile di un grafico aggiungendo un altro argomento dopo i due array. Questo argomento dovrà essere una stringa(quindi racchiuso tra' ' oppure " ") e contenere alcuni dei seguenti caratteri(ne elenco pochi, una lista completa è nell'help):
| r | colore rosso |
| g | colore verde |
| b | colore blu (default) |
| . | un punto in corrispondenza di ogni punto(x(n), y(n)) |
| * | un asterisco in corrispondenza di ogni punto (x(n), y(n)) |
| - | una linea spezzata congiunge i punti (default) |
Esempio:
axis([1 1.001 0 0.5])

Avrete notato che ogni volta che chiamate la funzione plot, il grafico viene stampato in Octave in una finestra intitolata "figure 1.0" . Potrebbe essere comodo visualizzare contemporaneamente più grafici. Per fare ciò è necessario utilizzare la funzione figure(n) , dove l'argomento "n" è un numero intero. L'esecuzione di questo comando provoca l'apertura di una nuova finestra di grafico, intitolata "Figure n.0". (di default è figure(1))
figure(2)
plot(T,y,"*r")
axis([0 0.001])
plot(T,y,".g")
axis([0.2 0.201])
Abbiamo visto che ad ogni chiamata della funzione plot, il grafico precedentemente presente nella figura attiva viene cancellato e sostituito con quello nuovo.
Per plottare più grafici su una stessa figura invece, è necessario utilizzare il comando "hold on".
Esempio:
plot(T,y,"r-")
hold on
plot(T,y,"b*")
axis([1 1.001 0 0.5])
hold off

Ricordatevi di digitare "hold off" quando non volete più che il grafico "persista". Consiglio di aggiungere "hold off" alla fine di ogni script in cui si utilizza "hold on"per evitare strani comportamenti quando viene rieseguito.
In alternativa, è possibile plottare più grafici nella stessa figura utilizzando plot con un maggior numero di argomenti.
Se non vengono specificate opzioni di formato il grafico della prima coppia di vettori verrà rapresentato in "-b", mentre quello della seconda coppia in "-g"

Come detto, la trattazione di plot qui è incompleta, e rimando all'help della funzione per approfondimenti.
L'espressione wavread richiede l'argomento "filename" che è il nome del file riff/wave che si vuole caricare all'interno di Octave. Valgono le considerazioni fatte sopra a riguardo della home directory di octave ecc. Se avete seguito le mie indicazioni, sarà sufficiente avere il file wave nella vostra comoda directory sul desktop(o dove piùvia aggrada) e digitare
Così facendo nel vettore y vengono caricati i valori dei campioni contenuti nel file "ooops.wav".Vi consiglio di lavorare con file monofonici, è molto più semplice e non è necessario introdurre le matrici.
Spesso è comodo il seguente utilizzo di wavread, che permette di assegnare alle variabili y, fc, bps rispettivamente i valori dei campioni, la frequenza di campionamentoe il numero di bit per sample. In questa maniera potremo ad esempio usare fc e bps nei nostri calcoli, qualora ci sia necessario.
plot(y)
%come vettore di ascisse utilizza [1:length(y)]
%notate anche nel grafico che il vettore è già normalizzato tra -1 e 1

Potremo fare poi su questo vettore di valori tutti i conti che ci interessano, alla fine produrremo probabilmente un vettore, magari chiamato out, di dati elaborati,che vorremo in qualche maniera salvare come un file audio per poterlo ascoltare.
Con la funzione wavwrite(y,fc,bps,filename) ciò è possibile. "y" dev'essere un vettore contenente i campioni, "fc" è la frequenza di campionamento, "bps" il numero di bit persample con cui si vuole salvare il file, filename è una stringa contenene il nome del file di destinazione.
- blog di giuliomoro
- Login o registrati per inviare commenti

