Source code for neurokit2.signal.signal_binarize

# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import sklearn.mixture


[docs] def signal_binarize(signal, method="threshold", threshold="auto"): """**Binarize a continuous signal** Convert a continuous signal into zeros and ones depending on a given threshold. Parameters ---------- signal : Union[list, np.array, pd.Series] The signal (i.e., a time series) in the form of a vector of values. method : str The algorithm used to discriminate between the two states. Can be one of ``"mixture"`` (default) or ``"threshold"``. If ``"mixture"``, will use a Gaussian Mixture Model to categorize between the two states. If ``"threshold"``, will consider as activated all points which value is superior to the threshold. threshold : float If ``method`` is ``"mixture"``, then it corresponds to the minimum probability required to be considered as activated (if ``"auto"``, then 0.5). If ``method`` is ``"threshold"``, then it corresponds to the minimum amplitude to detect as onset. If ``"auto"``, takes the value between the max and the min. Returns ------- list A list or array depending on the type passed. Examples -------- .. ipython:: python import neurokit2 as nk import numpy as np import pandas as pd signal = np.cos(np.linspace(start=0, stop=20, num=1000)) binary = nk.signal_binarize(signal) @savefig p_signal_binarize.png scale=100% pd.DataFrame({"Raw": signal, "Binary": binary}).plot() @suppress plt.close() """ # Return appropriate type if isinstance(signal, list): binary = _signal_binarize(np.array(signal), method=method, threshold=threshold) signal = list(binary) elif isinstance(signal, pd.Series): signal = signal.copy() # Avoid annoying pandas warning binary = _signal_binarize(signal.values, method=method, threshold=threshold) signal = signal.astype(binary.dtype) signal[:] = binary else: signal = _signal_binarize(signal, method=method, threshold=threshold) return signal
def _signal_binarize(signal, method="threshold", threshold="auto"): method = method.lower() # remove capitalised letters if method == "threshold": binary = _signal_binarize_threshold(signal, threshold=threshold) elif method == "mixture": binary = _signal_binarize_mixture(signal, threshold=threshold) else: raise ValueError( "NeuroKit error: signal_binarize(): 'method' should be one of 'threshold' or 'mixture'." ) return binary # ============================================================================= # Methods # ============================================================================= def _signal_binarize_threshold(signal, threshold="auto"): if threshold == "auto": threshold = np.mean([np.nanmax(signal), np.nanmin(signal)]) if threshold == "mean": threshold = np.nanmean(signal) if threshold == "median": threshold = np.nanmedian(signal) binary = np.zeros(len(signal)) binary[signal > threshold] = 1 return binary def _signal_binarize_mixture(signal, threshold="auto"): if threshold == "auto": threshold = 0.5 # fit a Gaussian Mixture Model with two components clf = sklearn.mixture.GaussianMixture(n_components=2, random_state=333) clf = clf.fit(signal.reshape(-1, 1)) # Get predicted probabilities probability = clf.predict_proba(signal.reshape(-1, 1))[ :, np.argmax(clf.means_[:, 0]) ] binary = np.zeros(len(signal)) binary[probability >= threshold] = 1 return binary