• Non ci sono risultati.

Alcune misure di ciclovoltammetria possono prevedere molti cicli consecutivi dell’onda triangolare di tensione data in ingresso al sistema. In questa situazione è possibile che il segnale di corrente misurato non si assesti su una traccia stabile e presenti invece uno spostamento (drift) continuo della posizione dei picchi. L’algoritmo iterativo che segue (movingmin) è stato sviluppato per tracciare dinamicamente la posizione dei minimi locali nel ciclovoltammogramma; fornendo come input la posizione approssimativa del primo picco (quello del primo ciclo) e un intervallo in tensione entro cui cercare il secondo, l’algoritmo:

1. calcola la posizione esatta del primo picco;

2. si sposta sul secondo ciclo a pari valore di tensione (ascissa) e cerca il picco entro l’intervallo definito;

3. qualora non lo trovi, allarga l’intervallo di ricerca;

4. individuato il picco, reimposta l’intervallo di ricerca predefinito e identifica la po-sizione del picco trovato come nuovo punto di partenza per la ricerca del picco successivo. In alternativa l’algoritmo può non trovare alcun picco (condizione di monotonia della traccia) e arrestarsi. L’esecuzione si arresta comunque raggiunto l’ultimo ciclo.

Potendo essere le tracce monotòne si è previsto di ignorare picchi individuati agli estre-mi dell’intervallo di ricerca. Inoltre, essendo le tracce spesso affette da rumore in alta frequenza, si è previsto di ignorare anche i picchi individuati troppo vicino agli estremi dell’intervallo di ricerca, entro qualche millivolt.

Nei commenti al codice si parla di indici di riga globali per indicare quelli della matrice dati passata in input, così che l’indice 1 indica effettivamente la prima riga dati; si parla di indici di riga locali per indicare quelli di porzioni della matrice dati elaborate separata-mente, così che l’indice 1 di queste sottomatrici non corrisponde all’indice 1 della matrice dati di partenza.

function out = movingmin( data, peakv, deltav, flag )

% INPUT: matrice dati, valore approssimato (in volt) del picco ( = minimo % locale) del PRIMO ciclo, valore minimo (in volt) dell'intorno entro cui % spostarsi per la ricerca dei minimi successivi.

% Flag: se = 0 indica il regolare funzionamento della function. Chiamare la % function con flag = 1 e' pensato per uso interno (la function e' ricorsiva) % e indica che peakv e deltav sono gia' indici della matrice e non valori di % tensione.

% OUTPUT: matrice [localmin current, localmin potential, indici matrice (per % uso interno alla ricorsione)].

langdsout=langds(data);

%langds OUTPUT: [rowsegm rowcyc cyclenumber maxindex

% Vinit Vmax Vmin step ]

rowsegm=langdsout(1,1); rowcyc=langdsout(1,2); cyclenumber=langdsout(1,3); maxindex=langdsout(1,4); stepv=langdsout(2,4); minstepv = 10*stepv;

persistent getout; %visibile anche nelle istanze generate per ricorsione

getout = 0;

%definisco l'intervallo entro cui cercare il minimo

if flag == 0

if deltav < minstepv

deltav = minstepv;

disp(horzcat('Too low voltage delta. Value increased to ',...

num2str(minstepv))); end

delta=round(deltav/stepv); else

delta=deltav; %se flag =1 sto gia' ragionando con intervalli di indici

%e non di tensione end

% Per Vinit = Vhigh i minimi assoluti vanno calcolati sui soli segmenti PARI % di indici da rowsegm*(N−1)+1 a rowsegm*N+1 con N pari (scrivo N

% come N=2n, n=1,2,3...). Qualora sia Vinit = Vlow,sostituire la % definizione di lowerbound e higherbound rispettivamente con 1 e % rowsegm+1

if flag == 0

start = −1;

lowerbound = rowsegm+1; % boundaries del primo segmento PARI

higherbound = rowsegm*2+1;

for ind = lowerbound:higherbound % cerco peakv nel primo segmento pari...

if (data(ind,1) == peakv)

start = ind; % ...e recupero l'indice associato

%NB: start e' inizializzato con un valore di indice del primo %ciclo, "globale", non scalato di un segmento.

break;

end end

if (start == −1)

disp ('Cannot find start point');

end else

start = peakv; %se flag =1 sto gia' ragionando con un valore di indice

%e non di tensione end

localmin_i=zeros(1,cyclenumber); %prealloco spazio per le matrici

localmin_v=zeros(1,cyclenumber); localmin_index=zeros(1,cyclenumber); scarto = 4;

% Eseguo la ricerca dei minimi lastdata=cyclenumber;

for n=1:cyclenumber

if getout == 1

%Se l'ultima iterazione avente un massimo era la 18 (n=18),

%durante il ciclo for con n=19 ho posto getout = 1 nel blocco elseif %e il successivo comando continue mi ha passato a n=20; quindi

%ho dati non nulli fino all'indice n−2 lastdata=n−2;

break;

end

lowerbound = rowsegm*(2*n−1)+1; % lowerbound e' indice globale

higherbound = rowsegm*2*n+1; % higherbound e' indice globale

% Qualora sia Vinit = Vlow, sostituire la definizione di lowerbound e % higherbound rispettivamente con rowsegm*(2*n−2)+1 e rowsegm*(2*n−1)+1

if higherbound > maxindex

higherbound=maxindex; end

low = start − delta; % valori dell'intorno definito da start e delta.

% low e high sono indici globali

if low < lowerbound

low = lowerbound; end

high = start + delta;

if high > higherbound

high = higherbound; end

% NB e' necessario che START sia un indice GLOBALE anche nelle % chiamate ricorsive

[curr, potindex]=min(data(low:high,2));

%NB: potindex e' indice locale dentro data(low:high), %(se potindex = 1 il minimo e' su low)

%converto potindex a indice globale:

potindex = low + potindex − 1;

%Devo garantirmi che il min sia ragionevolmente lontano dagli estremi: if (potindex < high − scarto)&&(potindex > low + scarto)

localmin_i(n)=curr;

localmin_v(n)=data(potindex,1); localmin_index(n)=potindex;

start = potindex + rowcyc; %start e' un indice globale

elseif high−low == rowsegm

%funzione monotona, mi fermo e interrompo %ogni istanza. Uso la variabile globale getout getout = 1;

continue;

%passa alla prossima iterazione del ciclo for. Getout %provvedera a uscirne

else %se non intercetto il minimo devo allargare il range

%di osservazione. Richiamo movingmin con delta %incrementato di 5*scarto

temp = movingmin(data(rowcyc*(n−1)+1:rowcyc*n+1,:),...

start−(n−1)*rowcyc,delta+5*scarto,1);

localmin_v(n)=temp(2,1); localmin_index(n)=temp(3,1);

%Dal valore di potindex ottenuto dalla chiamata iterativa aggiorno %il valore di start per la successiva iterazione del ciclo for. %NB: devo avanzare di un ciclo

start = temp(3,1)+n*rowcyc; end end out = [localmin_i(1:lastdata);localmin_v(1:lastdata);... localmin_index(1:lastdata)]; end

I dati estratti possono essere impiegati per tracciare un grafico che evidenzi ciclo per ciclo la posizione dei minimi locali. Un esempio è riportato in Figura C.1.

−0.4 −0.2 0 0.2 0.4 0.6 0.8 −25 −20 −15 −10 −5 0 5 10 15 20 Potential (V) Current ( µ A)

Figura C.1: Esempio di esecuzione dell’algoritmo movingmin. In nero i minimi locali rilevati. Traccia: ciclovoltammetria di ferricianuro 1 mM in DMEM, 75 cicli, ν = 100 mV/s, quiet time = 2 s.