Frequency spectrum¶
UML diagrams presenting the flow of the analysis for each module are available here: https://github.com/ANCPLabOldenburg/MEG-QC-code/tree/main/diagrams
- meg_qc.calculation.metrics.PSD_meg_qc.PSD_meg_qc(psd_params: dict, channels: dict, chs_by_lobe: dict, raw_orig: Raw, m_or_g_chosen: list, verbose_plots: bool, helperplots: bool)[source]¶
Main psd function. Calculates:
PSD for each channel
- amplitudes (area under the curve) of functionally distinct frequency bands, such as
delta (0.5-4 Hz), theta (4-8 Hz), alpha (8-12 Hz), beta (12-30 Hz), and gamma (30-100 Hz) for each channel and average amplitude of band over all channels
average psd over all channels
noise frequencies for average psd + creates a band around them
noise frequencies for each channel + creates a band around them
noise amplitudes (area under the curve) for each noisy frequency band for average psd
noise amplitudes (area under the curve) for each noisy frequency band for each channel.
Frequency spectrum peaks we can often see:
Hz 50, 100, 150 - powerline EU
Hz 60, 120, 180 - powerline US
Hz 6 - noise of shielding chambers
Hz 44 - MEG device noise
Hz 17 - train station
Hz 10 - specific for MEG device in Nessy
Hz 1 - highpass filter.
flat frequency spectrum is white noise process. Has same energy in every frequency (starts around 50Hz or even below)
- Parameters:
psd_params (dict) – dictionary with psd parameters originating from config file
channels (dict) – dictionary with channel names for each channel type: ‘mag’ or/and ‘grad’
chs_by_lobe (dict) – dictionary with channel objects sorted by ch type and lobe
raw_orig (mne.io.Raw) – raw data
m_or_g_chosen (list) – list with chosen channel types: ‘mag’ or/and ‘grad’
verbose_plots (bool) – True for showing plot in notebook.
helperplots (bool) – if True, plots with noisy freq bands for average PSD + for 3 different channels will be created (but not added to report).
- Returns:
derivs_psd (list) – list with the psd derivatives as QC_derivative objects (figures)
simple_metric (dict) – dictionary with the psd simple metrics
psd_str (str) – string with notes about PSD for report
noisy_freqs_global (dict) – dictionary with noisy frequencies for average psd - used in Muscle artifact detection
- meg_qc.calculation.metrics.PSD_meg_qc.Plot_psd_old(m_or_g: str, freqs: ndarray, psds: ndarray, channels: list, chs_by_lobe: dict, method: str, verbose_plots: bool)[source]¶
Plotting Power Spectral Density for all channels. OLD version
- Parameters:
m_or_g (str) – ‘mag’ or ‘grad’
freqs (np.ndarray) – frequencies
psds (np.ndarray) – power spectral density for each channel
channels (list) – list of channel names
chs_by_lobe (dict) – dictionary with channel objects sorted by lobe
method (str) – ‘welch’ or ‘multitaper’ or other method
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
QC_derivative object with plotly figure as content
- Return type:
- meg_qc.calculation.metrics.PSD_meg_qc.add_log_buttons(fig: Figure)[source]¶
Add buttons to switch scale between log and linear. For some reason only swithcing the Y scale works so far.
- Parameters:
fig (go.Figure) – The figure to be modified withot buttons
- Returns:
fig – The modified figure with the buttons
- Return type:
go.Figure
- meg_qc.calculation.metrics.PSD_meg_qc.assign_psds_to_channels(chs_by_lobe, freqs, psds)[source]¶
TODO: fix docstrings TODO: move as a part of MEG_channels in plots
Assign std or ptp values of each epoch as list to each channel. This is done for easier plotting when need to plot epochs per channel and also color coded by lobes.
- Parameters:
what_data (str) – ‘peaks’ for peak-to-peak amplitudes or ‘stds’
chs_by_lobe (dict) – dictionary with channel objects sorted by lobe.
df_std_ptp (pd.DataFrame) – Data Frame containing std or ptp value for each chnnel and each epoch
- Returns:
chs_by_lobe – updated dictionary with channel objects sorted by lobe - with info about std or ptp of epochs.
- Return type:
dict
- meg_qc.calculation.metrics.PSD_meg_qc.cut_the_noise_from_psd(noisy_bands_indexes: List[dict], freqs: list, one_psd: list, helper_plots: bool, ch_name: str = '', noisy_freqs_indexes: list = [], unit: str = '', verbose_plots: bool = True)[source]¶
Cut the noise peaks out of PSD curve. By default, it is not used, but can be turned on. If turned on, in the next steps, the area under the curve will be calculated only for the cut out peaks.
By default, the area under the curve is calculated under the whole peak, uncluding the ‘main brain signal’ psd area + peak area. This is done, because in reality we can not define, which part of the ‘noisy’ frequency is signal and which is noise. In case later, during preprocessing this noise will be filtered out, it will be done completely: both the peak and the main psd area.
Process:
Find the height of the noise peaks. For this take the average between the height of the start and end of this noise bend.
Cut the noise peaks out of PSD curve at the found height.
Baseline the peaks: all the peaks are brought to 0 level.
Function also can prodece helper plot to demonstrate the process.
- Parameters:
noisy_bands_indexes (list[list]) – list of lists with indexes of noisy bands. Indexes! Not frequency bands themselves. Index is defined by fequency/freq_resolution.
freqs (list) – vector of frequencies
one_psd (list) – vector if psd values for 1 channel (or 1 average over all channels)
helper_plots (bool) – if True, helper plots will be produced
ch_name (str, optional) – channel name, by default ‘’, used for plot display
noisy_freqs_indexes (list, optional) – list of indexes of noisy frequencies. Indexes! not frequencies themselves. Index is defined by fequency/freq_resolution., by default [] because we might have no noisy frequencies at all. Used for plot display.
unit (str, optional) – unit of the psd values, by default ‘’, used for plot display
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
psd_only_peaks_baselined – vector of psd values for 1 channel (or 1 average over all channels) with the noise peaks cut out and baselined to 0 level. Later used to calculate area under the curve for the noise peaks only.
- Return type:
list
- meg_qc.calculation.metrics.PSD_meg_qc.find_noisy_freq_bands_complex(ch_name: str, freqs: list, one_psd: list, helper_plots: bool, m_or_g: str, prominence_lvl_pos: int, verbose_plots: bool)[source]¶
Detect the frequency band around the noise peaks. Complex approach: This function is trying to detect the actual start and end of peaks.
Bands around the noise frequencies are created based on detected peak_width.
If the found bands overlap, they are cut at the lowest point between 2 neighbouring noise peaks pn PSD curve.
This function is not used by default, becausesuch a complex approach, even though can accurately find start and end of the noise bands, is not very robust. It can sometimes take too much of the area arouund the noise peak, leading to a large part of the signel folsely counted as noise. By default, the more simple approach is used. See find_noisy_freq_bands_simple() function.
- Parameters:
ch_name (str) – channel name like ‘MEG1234’ or just ‘Average’. For plotting purposes only.
freqs (list) – list of frequencies
one_psd (list) – list of psd values for one channels or for the average over multiple channels
helper_plots (bool) – if True, helper plots will be shown
m_or_g (str) – ‘mag’ or ‘grad’ - for plotting purposes only - to get the unit of the psd values
prominence_lvl_pos (int) – prominence level for peak detection. The higher the value, the more peaks will be detected.
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
noisy_freqs (list) – list of noisy frequencies
noisy_freqs_indexes (list) – list of indexes of noisy frequencies in the psd
noisy_bands_final (list[list]) – list of lists of noisy frequency bands. Each list contains 2 values: start and end of the band.
noisy_bands_final_indexes (list[list]) – list of lists of indexes of noisy frequency bands. Each list contains 2 values: start and end of the band.
split_indexes (list) – list of indexes of the split points in the psd
- meg_qc.calculation.metrics.PSD_meg_qc.find_noisy_freq_bands_simple(ch_name: str, freqs: list, one_psd: list, helper_plots: bool, m_or_g: str, prominence_lvl_pos: int, band_half_length: float, verbose_plots: bool)[source]¶
Form a frequency band around the noise peaks. Simple approach: used by default.
Create frequency band around central noise frequency just by adding -x…+x Hz around.
If the found bands overlap, they are cut at the lowest point between 2 neighbouring noise peaks pn PSD curve.
- Parameters:
ch_name (str) – channel name like ‘MEG1234’ or just ‘Average’. For plotting purposes only.
freqs (list) – list of frequencies
one_psd (list) – list of psd values for one channels or for the average over multiple channels
helper_plots (bool) – if True, helper plots will be shown
m_or_g (str) – ‘mag’ or ‘grad’ - for plotting purposes only - to get the unit of the psd values
prominence_lvl_pos (int) – prominence level for peak detection. The higher the value, the more peaks will be detected.
band_half_length (float) – length of the frequency band before and after the noise peak in Hz. The band will be created by adding -band_half_length…+band_half_length Hz around the noise peak.
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
noisy_freqs (list) – list of noisy frequencies
noisy_freqs_indexes (list) – list of indexes of noisy frequencies in the psd
noisy_bands_final (list[list]) – list of lists of noisy frequency bands. Each list contains 2 values: start and end of the band.
noisy_bands_final_indexes (list[list]) – list of lists of indexes of noisy frequency bands. Each list contains 2 values: start and end of the band.
split_indexes (list) – list of indexes of the split points in the psd
- meg_qc.calculation.metrics.PSD_meg_qc.find_number_and_ampl_of_noise_freqs(ch_name: str, freqs: list, one_psd: list, pie_plotflag: bool, helper_plots: bool, m_or_g: str, cut_noise_from_psd: bool, prominence_lvl_pos: int, simple_or_complex: str = 'simple', verbose_plots: bool = True)[source]¶
The function finds the number and amplitude of noisy frequencies in PSD function in these steps:
Calculate average psd curve over all channels
Run peak detection on it -> get number of noise freqs. Create the bands around them. Split blended freqs.
(Optional) Fit a curve to the general psd OR cut the noise peaks at the point they start and baseline them to 0. Optional. By default not used
- Calculate area under the curve for each noisy peak (amplitude of the noise)):
If 3 was done: area is limited to where noise band crosses the fitted curve. - count from there.
If not (default): area is limited to the whole area under the noise band, including the psd of the signal.
Calculate what part of the whole psd is the noise (noise amplitude) and what part is the signal (signal amplitude) + plot as pie chart
- Parameters:
ch_name (str) – name of the channel or ‘average’
freqs (list) – list of frequencies
one_psd (list) – list of psd values for one channel or average psd
pie_plotflag (bool) – if True, plot the pie chart
helper_plots (bool) – if True, plot the helper plots (will show the noise bands, how they are split and how the peaks are cut from the psd if this is activated).
m_or_g (str) – ‘mag’ or ‘grad’
cut_noise_from_psd (bool) – if True, cut the noise peaks at the point they start and baseline them to 0. Optional. By default not used
prominence_lvl_pos (int) – prominence level for peak detection (central frequencies of noise bands). The higher the value, the more peaks will be detected. prominence_lvl will be different for average psd and psd of 1 channel, because average has small peaks smoothed.
simple_or_complex (str) – ‘simple’ or ‘complex’ approach to create the bands around the noise peaks. Simple by default. See functions above for details.
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
noise_pie_derivative (list) – list with QC_derivative object containing the pie chart with the noise amplitude and signal amplitude
noise_ampl (list) – list of noise amplitudes for each noisy frequency band
noise_ampl_relative_to_signal (list) – list of noise amplitudes relative to the signal amplitude for each noisy frequency band
noisy_freqs (list) – list of noisy frequencies
- meg_qc.calculation.metrics.PSD_meg_qc.get_ampl_of_brain_waves(channels: list, m_or_g: str, freqs: ndarray, psds: ndarray, avg_psd: ndarray, plotflag: bool, verbose_plots: bool)[source]¶
Amplitude of frequencies calculation for all channels. If desired: creating a pie chart of mean amplitude of every band over the entire data.
- Parameters:
channels (list) – List of channel names
m_or_g (str) – ‘mag’ or ‘grad’ - to choose which channels to calculate amplitude for.
freqs (np.ndarray) – numpy array of frequencies for mag or grad
psds (np.ndarray) – numpy array of power spectrum dencities for mag or grad
avg_psd (np.ndarray) – numpy array of average power spectrum dencities for mag or grad
plotflag (bool) – need to plot pie chart or not
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
psd_pie_derivative (QC_derivative object or empty list) – If plotflag is True, returns one QC_derivative object, which is a plotly piechart figure. If plotflag is False, returns empty list.
dfs_with_name (list) – List of dataframes with amplitude of each frequency band in each channel (dfs: absolute amplitude, relative amplitude, amplitude divided by number of frequencies in the band)
mean_brain_waves_dict (dict) – Dictionary of mean amplitude of each frequency band (used for simple metric json)
- meg_qc.calculation.metrics.PSD_meg_qc.get_ampl_of_noisy_freqs(channels, freqs, avg_psd, psds, m_or_g, pie_plotflag=True, helperplots=True, cut_noise_from_psd=False, prominence_lvl_pos_avg=50, prominence_lvl_pos_channels=15, simple_or_complex='simple', verbose_plots: bool = True)[source]¶
Find noisy frequencies, their absolute and relative amplitude for averages over all channel (mag or grad) PSD and for each separate channel.
- Parameters:
channels (list) – list of channel names
freqs (list) – list of frequencies
avg_psd (list) – list of average PSD values over all channels
psds (list) – list of PSD values for each channel
m_or_g (str) – ‘mag’ or ‘grad’
pie_plotflag (bool) – if True, plot pie chart of SNR
helperplots (bool) – if True, plot helper plots
cut_noise_from_psd (bool) – if True, cut the noise peaks at the point they start and baseline them to 0.
prominence_lvl_pos_avg (int) – prominence level of peak detection for finding noisy frequencies in the average PSD
prominence_lvl_pos_channels (int) – prominence level of peak detection for finding noisy frequencies in the PSD of each channel
simple_or_complex (str) – ‘simple’ or ‘complex’ - method of finding noisy frequencies. see find_number_and_ampl_of_noise_freqs() for details
verbose_plots (bool) – True for showing plot in notebook.
- Returns:
noise_pie_derivative (QC_derivative object or empty list if pie_plotflag is False) – QC_derivative containig a pie chart of SNR
noise_ampl_global (dict) – dictionary for simple metric with info about noisy frequencies in the average PSD, absolute values for bands
noise_ampl_relative_to_all_signal_global (dict) – dictionary for simple metric with info about noisy frequencies in the average PSD, relative values for bands
noisy_freqs_global (dict) – dictionary for simple metric with info about noisy frequencies in the average PSD, central frequencies
noise_ampl_local_all_ch (dict) – dictionary for simple metric with info about noisy frequencies in the PSD of each channel, absolute values for bands
noise_ampl_relative_to_all_signal_local_all_ch (dict) – dictionary for simple metric with info about noisy frequencies in the PSD of each channel, relative values for bands
noisy_freqs_local_all_ch (dict) – dictionary for simple metric with info about noisy frequencies in the PSD of each channel, central frequencies
- meg_qc.calculation.metrics.PSD_meg_qc.get_mean_bands_amplitude(freq_bands: list, freqs: list, psds: ndarray, channels: list, bands_names: list | None = None)[source]¶
Calculate the area under the curve of frequency bands (e.g. alpha, beta, gamma, delta, …) for mag or grad. Adopted from: https://raphaelvallat.com/bandpower.html Take mean over all channels (mags/grads).
- Parameters:
freq_bands (list) – List of lists of frequencies. Expects list of lists: [[f_low, f_high], [f_low, f_high], …]
freqs (list) – List of frequencies.
psds (np.ndarray or list) – numpy array (or list) of power spectrum dencities. Expects array of arrays: channels*psds. (or list of lists) Will not work properly if 1 dimentional array given. In this case do: np.array([your_1d_array])
channels (list) – List of channel names. Expects list of strings: [‘MEG 0111’, ‘MEG 0112’, …] If only one channel is given, it should be a list of one string: [‘Average]
bands_names (list, optional) – List of names of the bands. If None, the names will be generated automatically, by default None Important! taht these names are in the same order as in freq_bands.
- Returns:
band_ampl_df (pd.DataFrame) – Dataframe of amplitudes of each frequency band like: [abs_power_of_delta, abs_power_of_gamma, etc…] - in absolute values
band_ampl_relative_to_signal_df (pd.DataFrame) – Dataframe of amplitudes of each frequency band divided by the total amplitudeof the signal for this channel. Shows how much amplitude this particular band takes in the entire signal.
ampl_by_Nfreq_per_ch_list_df (pd.DataFrame) – Dataframe of amplitudes of each frequency band divided by the number of frequencies in the band. (This is done to compare with RMSE later. But not used any more).
total_signal_amplitude (list) – List of total signal amplitude for each channel.
- meg_qc.calculation.metrics.PSD_meg_qc.get_nfft_nperseg(raw: Raw, psd_step_size: float)[source]¶
Get nfft and nperseg parameters for Welch psd function. Allowes to always have the step size in psd which is chosen by the user. Recommended 0.5 Hz.
- Parameters:
raw (mne.io.Raw) – raw data
psd_step_size (float) – step size for PSD chosen by user, recommended 0.5 Hz
- Returns:
nfft (int) – Number of points for fft. Used in welch psd function from mne. The length of FFT used, must be >= n_per_seg (default: 256). The segments will be zero-padded if n_fft > n_per_seg. If n_per_seg is None, n_fft must be <= number of time points in the data.
nperseg (int) – Number of points for each segment. Used in welch psd function from mne. Length of each Welch segment (windowed with a Hamming window). Defaults to None, which sets n_per_seg equal to n_fft.
- meg_qc.calculation.metrics.PSD_meg_qc.make_dict_global_psd(mean_brain_waves_dict: dict, noisy_freqs_global: list, noise_ampl_global: list, noise_ampl_relative_to_all_signal_global: list)[source]¶
Create a dictionary for the global part of psd simple metrics. Global: overall part of noise in the signal (all channels averaged).
- Parameters:
mean_brain_waves_dict (dict) – dictionary with the mean brain waves (alpha, beta, etc) metrics in the form: {wave band name: {mean realtive value, mean absolute value}, …}
noisy_freqs_global (list) – list of noisy frequencies
noise_ampl_global (list) – list of noise amplitudes for each noisy frequency band
noise_ampl_relative_to_all_signal_global (list) – list of noise amplitudes relative to the total signal amplitude for each noisy frequency band
- Returns:
dict_global – dictionary with the global part of psd simple metrics
- Return type:
dict
- meg_qc.calculation.metrics.PSD_meg_qc.make_dict_local_psd(noisy_freqs_local: dict, noise_ampl_local: dict, noise_ampl_relative_to_all_signal_local: dict, channels: list)[source]¶
Create a dictionary for the local part of psd simple metrics. Local: part of noise in the signal for each channel separately.
- Parameters:
noisy_freqs_local (dict) – dictionary with noisy frequencies for each channel
noise_ampl_local (dict) – dictionary with noise amplitudes for each noisy frequency band for each channel
noise_ampl_relative_to_all_signal_local (dict) – dictionary with noise amplitudes relative to the total signal amplitude for each noisy frequency band for each channel
- Returns:
dict_local – dictionary with the local part of psd simple metrics
- Return type:
dict
- meg_qc.calculation.metrics.PSD_meg_qc.make_simple_metric_psd(mean_brain_waves_dict: dict, noise_ampl_global: dict, noise_ampl_relative_to_all_signal_global: dict, noisy_freqs_global: dict, noise_ampl_local: dict, noise_ampl_relative_to_all_signal_local: dict, noisy_freqs_local: dict, m_or_g_chosen: list, freqs: dict, channels: dict)[source]¶
Create a dictionary for the psd simple metrics.
- Parameters:
mean_brain_waves_dict (dict) – dictionary with mean brain waves (alpha, beta, etc) for each channel type. Inside each channel type: dictionary in the form: {wave band name: {mean realtive value, mean absolute value}, …}
noise_ampl_global (dict) – dictionary with noise amplitudes for each noisy frequency band
noise_ampl_relative_to_all_signal_global (dict) – dictionary with noise amplitudes relative to the total signal amplitude for each noisy frequency band
noisy_freqs_global (dict) – dictionary with noisy frequencies
noise_ampl_local (dict) – dictionary with noise amplitudes for each noisy frequency band for each channel
noise_ampl_relative_to_all_signal_local (dict) – dictionary with noise amplitudes relative to the total signal amplitude for each noisy frequency band for each channel
noisy_freqs_local (dict) – dictionary with noisy frequencies for each channel
m_or_g_chosen (list) – list with chosen channel types: ‘mag’ or/and ‘grad’
- Returns:
simple_metric – dictionary with the psd simple metrics
- Return type:
dict
- meg_qc.calculation.metrics.PSD_meg_qc.plot_one_psd(ch_name: str, freqs: List, one_psd: List, peak_indexes: List, noisy_freq_bands_indexes: List[list], unit: str)[source]¶
Plot PSD for one channels or for the average over multiple channels with noise peaks and split points using plotly.
- Parameters:
ch_name (str) – channel name like ‘MEG1234’ or just ‘Average’
freqs (list) – list of frequencies
one_psd (list) – list of psd values for one channels or for the average over multiple channels
peak_indexes (list) – list of indexes of the noise peaks in the psd
noisy_freq_bands_indexes (list[list]) – list of lists of indexes of the noisy frequency bands in the psd. Indexes! Not frequency bands themselves. Index is defined by fequency/freq_resolution.
unit (str) – unit of the psd values. For example ‘T/Hz’
- Returns:
plotly figure of the psd with noise peaks and bands around them.
- Return type:
fig
- meg_qc.calculation.metrics.PSD_meg_qc.split_blended_freqs_at_the_lowest_point(noisy_bands_indexes: List[list], one_psd: List[dict], noisy_freqs_indexes: List[dict])[source]¶
If there are 2 bands that are blended together, split them at the lowest point between 2 central noise frequencies.
- Parameters:
noisy_bands_indexes (list[list]) – list of lists with indexes of noisy bands. Indexes! not frequency bands themselves. Index is defined by fequency/freq_resolution.
one_psd (list) – vector if psd values for 1 channel (or 1 average over all channels)
noisy_freqs_indexes (list) – list of indexes of noisy frequencies. Indexes! not frequencies themselves. Index is defined by fequency/freq_resolution.
- Returns:
noisy_bands_final_indexes (list[list]) – list of lists with indexes of noisy bands After the split. Indexes! not frequency bands themselves. Index is defined by fequency/freq_resolution.
split_indexes (list) – list of indexes at which the bands were split (used later for plotting only).