Znajdź różnicę fazową między dwoma falami (inharmonicznymi)

Mam dwa zbiory danych wymieniające średnie napięcia wyjściowe dwóch zespołów sieci neuronowych w czasie t, które wyglądają mniej więcej tak:

A = [-80.0, -80.0, -80.0, -80.0, -80.0, -80.0, -79.58, -79.55, -79.08, -78.95, -78.77, -78.45,-77.75, -77.18, -77.08, -77.18, -77.16, -76.6, -76.34, -76.35]

B = [-80.0, -80.0, -80.0, -80.0, -80.0, -80.0, -78.74, -78.65, -78.08, -77.75, -77.31, -76.55, -75.55, -75.18, -75.34, -75.32, -75.43, -74.94, -74.7, -74.68]

Gdy dwa zespoły neuronowe są" w fazie " w rozsądnym stopniu, oznacza to, że są ze sobą powiązane. Chcę obliczyć różnicę faz między A i B, najlepiej przez cały czas symulacji. Ponieważ dwa zespoły są mało prawdopodobne, aby być całkowicie w fazie, chcę porównać tę różnicę fazową do pewnego próg.

Są to oscylatory nieharmoniczne i nie znam ich funkcji, tylko te wartości, więc nie mam pojęcia, jak określić fazę lub odpowiednią różnicę fazową.

Wykonuję ten projekt w Pythonie, używając numpy i scipy(oba zespoły są tablicami numpy).

Wszelkie sugestie będą mile widziane!

EDIT: dodane działki

Przykładowy plik danych dla assembly 1

Przykładowy plik danych do montażu 2

Oto wykres, jak wyglądają dwa zbiory danych: Wykres dwóch zespołów neuronalnych nakładających się na siebieWykres dwóch zespołów neuronalnych

Author: Doa, 2011-05-28

2 answers

Być może szukasz korelacji krzyżowej:

scipy.​signal.​signaltools.correlate(A, B)

Położenie piku w korelacji krzyżowej będzie oszacowaniem różnicy faz.

EDIT 3: Update now that I have looked at the real data files. Istnieją dwa powody, dla których można znaleźć przesunięcie fazowe zera. Po pierwsze, przesunięcie fazowe jest zerowe między dwoma seriami czasowymi. Widać to wyraźnie, jeśli powiększysz Wykres matplotlib w poziomie. Po drugie, ważne jest, aby uregulować dane najpierw (co najważniejsze, odejmują od średniej), w przeciwnym razie efekt zerowego paddingu na końcach tablic powoduje, że sygnał rzeczywisty w korelacji krzyżowej. W poniższym przykładzie sprawdzam, czy znajduję" prawdziwy " szczyt, dodając sztuczne przesunięcie, a następnie sprawdzam, czy odzyskuję go poprawnie.

import numpy, scipy
from scipy.signal import correlate

# Load datasets, taking mean of 100 values in each table row
A = numpy.loadtxt("vb-sync-XReport.txt")[:,1:].mean(axis=1)
B = numpy.loadtxt("vb-sync-YReport.txt")[:,1:].mean(axis=1)

nsamples = A.size

# regularize datasets by subtracting mean and dividing by s.d.
A -= A.mean(); A /= A.std()
B -= B.mean(); B /= B.std()

# Put in an artificial time shift between the two datasets
time_shift = 20
A = numpy.roll(A, time_shift)

# Find cross-correlation
xcorr = correlate(A, B)

# delta time array to match xcorr
dt = numpy.arange(1-nsamples, nsamples)

recovered_time_shift = dt[xcorr.argmax()]

print "Added time shift: %d" % (time_shift)
print "Recovered time shift: %d" % (recovered_time_shift)

# SAMPLE OUTPUT:
# Added time shift: 20
# Recovered time shift: 20

EDIT: Oto przykład jak to działa z fałszywymi danymi.

EDIT 2: Dodano Wykres przykładu.

Korelacja krzyżowa hałaśliwych sygnałów anharmonicznych

import numpy, scipy
from scipy.signal import square, sawtooth, correlate
from numpy import pi, random

period = 1.0                            # period of oscillations (seconds)
tmax = 10.0                             # length of time series (seconds)
nsamples = 1000
noise_amplitude = 0.6

phase_shift = 0.6*pi                   # in radians

# construct time array
t = numpy.linspace(0.0, tmax, nsamples, endpoint=False)

# Signal A is a square wave (plus some noise)
A = square(2.0*pi*t/period) + noise_amplitude*random.normal(size=(nsamples,))

# Signal B is a phase-shifted saw wave with the same period
B = -sawtooth(phase_shift + 2.0*pi*t/period) + noise_amplitude*random.normal(size=(nsamples,))

# calculate cross correlation of the two signals
xcorr = correlate(A, B)

# The peak of the cross-correlation gives the shift between the two signals
# The xcorr array goes from -nsamples to nsamples
dt = numpy.linspace(-t[-1], t[-1], 2*nsamples-1)
recovered_time_shift = dt[xcorr.argmax()]

# force the phase shift to be in [-pi:pi]
recovered_phase_shift = 2*pi*(((0.5 + recovered_time_shift/period) % 1.0) - 0.5)

relative_error = (recovered_phase_shift - phase_shift)/(2*pi)

print "Original phase shift: %.2f pi" % (phase_shift/pi)
print "Recovered phase shift: %.2f pi" % (recovered_phase_shift/pi)
print "Relative error: %.4f" % (relative_error)

# OUTPUT:
# Original phase shift: 0.25 pi
# Recovered phase shift: 0.24 pi
# Relative error: -0.0050

# Now graph the signals and the cross-correlation

from pyx import canvas, graph, text, color, style, trafo, unit
from pyx.graph import axis, key

text.set(mode="latex")
text.preamble(r"\usepackage{txfonts}")
figwidth = 12
gkey = key.key(pos=None, hpos=0.05, vpos=0.8)
xaxis = axis.linear(title=r"Time, \(t\)")
yaxis = axis.linear(title="Signal", min=-5, max=17)
g = graph.graphxy(width=figwidth, x=xaxis, y=yaxis, key=gkey)
plotdata = [graph.data.values(x=t, y=signal+offset, title=label) for label, signal, offset in (r"\(A(t) = \mathrm{square}(2\pi t/T)\)", A, 2.5), (r"\(B(t) = \mathrm{sawtooth}(\phi + 2 \pi t/T)\)", B, -2.5)]
linestyles = [style.linestyle.solid, style.linejoin.round, style.linewidth.Thick, color.gradient.Rainbow, color.transparency(0.5)]
plotstyles = [graph.style.line(linestyles)]
g.plot(plotdata, plotstyles)
g.text(10*unit.x_pt, 0.56*figwidth, r"\textbf{Cross correlation of noisy anharmonic signals}")
g.text(10*unit.x_pt, 0.33*figwidth, "Phase shift: input \(\phi = %.2f \,\pi\), recovered \(\phi = %.2f \,\pi\)" % (phase_shift/pi, recovered_phase_shift/pi))
xxaxis = axis.linear(title=r"Time Lag, \(\Delta t\)", min=-1.5, max=1.5)
yyaxis = axis.linear(title=r"\(A(t) \star B(t)\)")
gg = graph.graphxy(width=0.2*figwidth, x=xxaxis, y=yyaxis)
plotstyles = [graph.style.line(linestyles + [color.rgb(0.2,0.5,0.2)])]
gg.plot(graph.data.values(x=dt, y=xcorr), plotstyles)
gg.stroke(gg.xgridpath(recovered_time_shift), [style.linewidth.THIck, color.gray(0.5), color.transparency(0.7)])
ggtrafos = [trafo.translate(0.75*figwidth, 0.45*figwidth)]
g.insert(gg, ggtrafos)
g.writePDFfile("so-xcorr-pyx")

Więc działa całkiem dobrze, nawet dla bardzo hałaśliwych danych i bardzo aharmonicznych fal.

 21
Author: deprecated,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-31 16:16:02

@ deprecated komentarze są dokładną odpowiedzią na pytanie, jeśli chodzi o rozwiązanie Pythona o czystym kodzie. Komentarze były bardzo cenne, ale czuję, że powinienem dodać kilka notatek dla osób szukających odpowiedzi w konkretnym kontekście sieci neuronowych.

Kiedy weźmiesz średni potencjał błonowy dużych zespołów neuronów, tak jak ja, korelacja będzie stosunkowo słaba. To, na co chcesz spojrzeć, przede wszystkim, jest albo korelacja między pociągami spike, opóźnienie lub pobudliwość (tj. skuteczność synaptyczna) poszczególnych zespołów. Można to znaleźć stosunkowo łatwo po prostu patrząc na punkty, w których potencjał przekracza pewien próg. Funkcja korelacji Scipy 'ego w pociągach spike' a pokaże znacznie bardziej szczegółowy obraz współzależności między neuronami lub zespołami neuronowymi, gdy podasz mu pociągi spike ' a, w przeciwieństwie do rzeczywistych potencjałów. Możesz również spojrzeć na moduł statystyki Briana, który można znaleźć tutaj:

Http://neuralensemble.org/trac/brian/browser/trunk/brian/tools/statistics.py

Jeśli chodzi o różnicę fazową, to prawdopodobnie jest to nieodpowiednia miara, ponieważ neurony nie są oscylatorami harmonicznymi. Jeśli chcesz wykonać bardzo precyzyjne pomiary faz, najlepiej przyjrzeć się synchronizacji oscylatorów harmonicznych. Model matematyczny opisujący tego rodzaju oscylatory, który jest bardzo przydatny w kontekście neuronów i sieci neuronowych, to Kuramoto model. Dostępna jest obszerna dokumentacja dla modelu Kuramoto i synchronizacji integracji i ognia, więc zostawię to.

 2
Author: Doa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-08 02:49:55