Coverage for brainbox/lfp.py: 0%
34 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-08 17:16 +0100
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-08 17:16 +0100
1# -*- coding: utf-8 -*-
2"""
3Functions to analyse LFP signals.
5@author: Guido Meijer
6Created on Fri Mar 13 14:57:53 2020
7"""
9from scipy.signal import welch, csd, filtfilt, butter
10import numpy as np
13def butter_filter(signal, highpass_freq=None, lowpass_freq=None, order=4, fs=2500):
15 # The filter type is determined according to the values of cut-off frequencies
16 Fn = fs / 2.
17 if lowpass_freq and highpass_freq:
18 if highpass_freq < lowpass_freq:
19 Wn = (highpass_freq / Fn, lowpass_freq / Fn)
20 btype = 'bandpass'
21 else:
22 Wn = (lowpass_freq / Fn, highpass_freq / Fn)
23 btype = 'bandstop'
24 elif lowpass_freq:
25 Wn = lowpass_freq / Fn
26 btype = 'lowpass'
27 elif highpass_freq:
28 Wn = highpass_freq / Fn
29 btype = 'highpass'
30 else:
31 raise ValueError("Either highpass_freq or lowpass_freq must be given")
33 # Filter signal
34 b, a = butter(order, Wn, btype=btype, output='ba')
35 filtered_data = filtfilt(b=b, a=a, x=signal, axis=1)
37 return filtered_data
40def power_spectrum(signal, fs=2500, segment_length=0.5, segment_overlap=0.5, scaling='density'):
41 """
42 Calculate the power spectrum of an LFP signal
44 Parameters
45 ----------
46 signal : 2D array
47 LFP signal from different channels in V with dimensions (channels X samples)
48 fs : int
49 Sampling frequency
50 segment_length : float
51 Length of the segments for which the spectral density is calcualted in seconds
52 segment_overlap : float
53 Fraction of overlap between the segments represented as a float number between 0 (no
54 overlap) and 1 (complete overlap)
56 Returns
57 ----------
58 freqs : 1D array
59 Frequencies for which the spectral density is calculated
60 psd : 2D array
61 Power spectrum in V^2 with dimensions (channels X frequencies)
63 """
65 # Transform segment from seconds to samples
66 segment_samples = int(fs * segment_length)
67 overlap_samples = int(segment_overlap * segment_samples)
69 # Calculate power spectrum
70 freqs, psd = welch(signal, fs=fs, nperseg=segment_samples, noverlap=overlap_samples,
71 scaling=scaling)
72 return freqs, psd
75def coherence(signal_a, signal_b, fs=2500, segment_length=1, segment_overlap=0.5):
76 """
77 Calculate the coherence between two LFP signals
79 Parameters
80 ----------
81 signal_a : 1D array
82 LFP signal from different channels with dimensions (channels X samples)
83 fs : int
84 Sampling frequency
85 segment_length : float
86 Length of the segments for which the spectral density is calcualted in seconds
87 segment_overlap : float
88 Fraction of overlap between the segments represented as a float number between 0 (no
89 overlap) and 1 (complete overlap)
91 Returns
92 ----------
93 freqs : 1D array
94 Frequencies for which the coherence is calculated
95 coherence : 1D array
96 Coherence takes a value between 0 and 1, with 0 or 1 representing no or perfect coherence,
97 respectively
98 phase_lag : 1D array
99 Estimate of phase lag in radian between the input time series for each frequency
101 """
103 # Transform segment from seconds to samples
104 segment_samples = int(fs * segment_length)
105 overlap_samples = int(segment_overlap * segment_samples)
107 # Calculate coherence
108 freqs, Pxx = welch(signal_a, fs=fs, nperseg=segment_samples, noverlap=overlap_samples)
109 _, Pyy = welch(signal_b, fs=fs, nperseg=segment_samples, noverlap=overlap_samples)
110 _, Pxy = csd(signal_a, signal_b, fs=fs, nperseg=segment_samples, noverlap=overlap_samples)
111 coherence = np.abs(Pxy) ** 2 / (Pxx * Pyy)
112 phase_lag = np.angle(Pxy)
114 return freqs, coherence, phase_lag